home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / OGRID110 / GLCELL.PAS < prev    next >
Pascal/Delphi Source File  |  1995-06-01  |  85KB  |  2,650 lines

  1. {*****************************************************************************
  2.  
  3.   OOGrid Library(TM) for Borland/Turbo Pascal (Real Mode/TV)
  4.   Copyright (C) 1994, 1995 by Arturo J. Monge
  5.   Portions Copyright (C) 1989,1990 Borland International, Inc.
  6.  
  7.   OOGrid Library(TM) Cell Unit:
  8.     This unit implements the different types of cells and hash tables
  9.     used by the TSpreadSheet object. The hash tables are descendants of
  10.     Borland's HashTable object. For more information, see TCHASH.PAS (in
  11.     Turbo Pascal 6.0).
  12.  
  13.     Basically, this unit is the same as Borland's TCCELL.PAS but
  14.     with a large amount of modifications which were necessary
  15.     for adapting the unit's objects for use by the TSpreadSheet
  16.     object.
  17.  
  18.   Copyright (C) 1989, 1990 Borland international, Inc.
  19.   Portions Copyright (C) 1994 by Arturo J. Monge
  20.  
  21.   Last Modification : December 29th, 1994
  22.  
  23. *****************************************************************************}
  24.  
  25. {$O+,F+,N+,E+,X+}
  26.  
  27. unit GLCell;
  28.  
  29. {****************************************************************************}
  30.                                  interface
  31. {****************************************************************************}
  32.  
  33. uses Objects, TCUtil, TCHash, GLLStr, GLSupprt, GLEquate;
  34.  
  35. const
  36.   { Characters that are used to indicate a certain type of cell }
  37.   RepeatFirstChar = '\';
  38.   TextFirstChar = ' ';
  39.  
  40.   { Bits used to determine a cell's format }
  41.   CommasPart = $80;
  42.   CurrencyCharPart = $FF00;
  43.   CurrencyPart = $40;
  44.   DecPlacesPart = $0F;
  45.   JustPart = $03;
  46.  
  47.   { Used in the determination of a cell's format }
  48.   CurrencyShift = 8;
  49.   JustShift = 4;
  50.   NumberFormatShift = 6;
  51.  
  52. type
  53.   CellTypes = (ClEmpty, ClValue, ClText, ClFormula, ClRepeat);
  54.   CurrencyStr = String[3];
  55.   FormatType = Word;
  56.   Justification = (JLeft, JCenter, JRight);
  57.  
  58.   PCell = ^TCell;
  59.  
  60.   PHashTable = ^THashTable;
  61.   THashTable = OBJECT(HashTable)
  62.   { A HashTable descendant that won't allow the addition of a new cell
  63.     if LowMemory is true }
  64.      function Add: Boolean;
  65.   end; {...THashTable }
  66.  
  67.   PCellHashTable = ^TCellHashTable;
  68.   TCellHashTable = OBJECT(THashTable)
  69.   { A THashTable's descendant that stores pointers to cells in a spreadsheet
  70.     and the associated cells' contents }
  71.         CurrCell : PCell;
  72.         CurrLoc : CellPos;
  73.      constructor Init(InitBuckets : BucketRange);
  74.      destructor Done;
  75.      function Add(ACell : PCell) : Boolean;
  76.      procedure Delete(DelLoc : CellPos; var DeletedCell : PCell);
  77.      function Search(SPos : CellPos) : PCell;
  78.      function HashValue : LongInt; virtual;
  79.      function Found(Item : HashItemPtr) : Boolean; virtual;
  80.      procedure CreateItem(var Item : HashItemPtr); virtual;
  81.      function ItemSize : HashItemSizeRange; virtual;
  82.      procedure Load(var S : TStream; Total : Longint;
  83.        AdjustAfter: CellPos; RowAdjustment, ColAdjustment: Integer);
  84.      procedure Store(var S : TStream);
  85.      function FirstItem : PCell;
  86.      function NextItem : PCell;
  87.   end; {...TCellHashTable }
  88.  
  89.   PFormatHashTable = ^TFormatHashTable;
  90.   TFormatHashTable = OBJECT(THashTable)
  91.   { A THashTable's descendant that stores the format values assigned to
  92.     blocks of cells in a spreadsheet }
  93.        CurrStart,
  94.        CurrStop : CellPos;
  95.        CurrFormat : FormatType;
  96.     constructor Init;
  97.     destructor Done;
  98.     function Overwrite(NewStart, NewStop : CellPos) : Boolean;
  99.     function Add(NewStart, NewStop : CellPos;
  100.       NewFormat : FormatType) : Boolean;
  101.     function Delete(DStart, DStop : CellPos) : Boolean;
  102.     function Search(SPos : CellPos; var F : FormatType) : Boolean;
  103.     function HashValue : LongInt; virtual;
  104.     function Found(Item : HashItemPtr) : Boolean; virtual;
  105.     procedure CreateItem(var Item : HashItemPtr); virtual;
  106.     function ItemSize : HashItemSizeRange; virtual;
  107.     procedure Load(var S : TStream; Total : Longint);
  108.     procedure Store(var S : TStream);
  109.   end; {...TFormatHashTable }
  110.  
  111.   PWidthHashTable = ^TWidthHashTable;
  112.   TWidthHashTable = OBJECT(THashTable)
  113.   { A THashTable's descendant that stores the widths of the columns in
  114.     a spreadsheet }
  115.        CurrCol : Word;
  116.        CurrWidth : Byte;
  117.        DefaultColWidth : Byte;
  118.     constructor Init(InitBuckets : BucketRange; InitDefaultColWidth : Byte);
  119.     destructor Done;
  120.     function Add(SCol : Word; NewWidth : Byte) : Boolean;
  121.     procedure Delete(Col : Word);
  122.     function Search(Col : Word) : Byte;
  123.     function HashValue : LongInt; virtual;
  124.     function Found(Item : HashItemPtr) : Boolean; virtual;
  125.     procedure CreateItem(var Item : HashItemPtr); virtual;
  126.     function ItemSize : HashItemSizeRange; virtual;
  127.     function GetDefaultColWidth : Byte;
  128.     procedure Load(var S : TStream; Total : Longint);
  129.     procedure Store(var S : TStream);
  130.   end; {...TWidthHashTable }
  131.  
  132.   GetColWidthFunc = function(var WHash : TWidthHashTable;
  133.                              C : Word) : Byte;
  134.   { Used by the cell objects to get the width of the column they
  135.     are located in; also used by the TOverwriteHashTable object }
  136.  
  137.   POverwriteHashTable = ^TOverwriteHashTable;
  138.   TOverwriteHashTable = OBJECT(THashTable)
  139.   { A THashTable's descendant that keeps track of which cells are overwriten
  140.     by other cells }
  141.       CurrCell : PCell;
  142.       CurrPos : CellPos;
  143.       EndCol : Word;
  144.     constructor Init(InitBuckets : BucketRange);
  145.     destructor Done;
  146.     function Add(SCell : PCell; var CHash: TCellHashTable;
  147.                  var FHash: TFormatHashTable; var WHash: TWidthHashTable;
  148.                  LastPos: CellPos; MaxCols: Word;
  149.                  GetColWidth: GetColWidthFunc; FormulasDisplayed,
  150.                  ChangeYes: Boolean) : Boolean;
  151.     procedure Delete(SPos : CellPos; var CHash: TCellHashTable;
  152.                      var FHash: TFormatHashTable; var WHash: TWidthHashTable;
  153.                      LastPos: CellPos; MaxCols: Word;
  154.                      GetColWidth: GetColWidthFunc;
  155.                      FormulasDisplayed, ChangeYes: Boolean);
  156.     function Change(SCell : PCell; Overwritten : Word) : Boolean;
  157.     function Search(SPos : CellPos) : PCell;
  158.     function HashValue : LongInt; virtual;
  159.     function Found(Item : HashItemPtr) : Boolean; virtual;
  160.     procedure CreateItem(var Item : HashItemPtr); virtual;
  161.     function ItemSize : HashItemSizeRange; virtual;
  162.   end; {...TOverwriteHashTable }
  163.  
  164.    PUnLockedCellHashTable = ^TUnlockedHashTable;
  165.    TUnlockedHashTable = OBJECT(THashTable)
  166.    { A THashTable's descendant that keeps track of unlocked areas }
  167.          CurrStart,
  168.          CurrStop : CellPos;
  169.       constructor Init;
  170.       function Add(NewStart, NewStop: CellPos): Boolean;
  171.       procedure CreateItem(var Item: HashItemPtr); virtual;
  172.       function Delete(DStart, DStop: CellPos): Boolean;
  173.       function Found(Item: HashItemPtr): Boolean; virtual;
  174.       function HashValue : LongInt; virtual;
  175.       function ItemSize : HashItemSizeRange; virtual;
  176.       constructor Load(var S: TStream; Total: Longint);
  177.       function Overwrite(NewStart, NewStop: CellPos): Boolean;
  178.       function Search(SPos: CellPos): Boolean;
  179.       procedure Store(var S: TStream);
  180.       destructor Done;
  181.    end; {...TUnlockedHashTable }
  182.  
  183.  
  184.    PColumnHeadersHashTable = ^THeadersHashTable;
  185.    THeadersHashTable = OBJECT(THashTable)
  186.    { A THashTable's descendant that stores custom assigned column headers }
  187.         CurrCol : Word;
  188.         CurrName : String[80];
  189.      constructor Init(InitBuckets : BucketRange);
  190.      function Add(SCol : Word; NewName: String) : Boolean;
  191.      procedure CreateItem(var Item : HashItemPtr); virtual;
  192.      procedure Delete(Col : Word);
  193.      function Found(Item : HashItemPtr) : Boolean; virtual;
  194.      function HashValue : LongInt; virtual;
  195.      function ItemSize : HashItemSizeRange; virtual;
  196.      procedure Load(var S : TStream; Total : Longint);
  197.      function Search(Col : Word; var Name: String) : Boolean;
  198.      function SearchName(Name: String; var Col: Word) : Boolean;
  199.      procedure Store(var S : TStream);
  200.      destructor Done;
  201.    end; {...THeadersHashTable }
  202.  
  203.  
  204.   TCell = OBJECT(TObject)
  205.   { This is the main cell object.  You'll never construct an instance of
  206.     TCell object itself; rather you'll use one or more of TCell's derived
  207.     object types: TEmptyCell, TTextCell, TValueCell, TFormulaCell,
  208.     TRepeatCell or create new derived object types }
  209.        Loc : CellPos;
  210.     constructor Init(InitLoc : CellPos);
  211.     destructor Done; virtual;
  212.     function CellType : CellTypes; virtual;
  213.     function LegalValue : Boolean; virtual;
  214.     function Name : String; virtual;
  215.     function Format(var FHash : TFormatHashTable;
  216.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  217.     function Width(var FHash : TFormatHashTable;
  218.                    FormulasDisplayed : Boolean) : Word; virtual;
  219.     function Overwritten(var CHash : TCellHashTable;
  220.                          var FHash : TFormatHashTable;
  221.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  222.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  223.                          FormulasDisplayed : Boolean) : Word; virtual;
  224.     function ShouldUpdate : Boolean; virtual;
  225.     function HasError : Boolean; virtual;
  226.     function CurrValue : Extended; virtual;
  227.     function OverwriteStart(var FHash : TFormatHashTable;
  228.                             var WHash : TWidthHashTable;
  229.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  230.                             DisplayFormulas : Boolean) : Word; virtual;
  231.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  232.     function DisplayString(FormulasDisplayed : Boolean;
  233.                            MaxDecPlaces : Byte) : String; virtual;
  234.     function FormattedString(var OHash : TOverWriteHashTable;
  235.                              var FHash : TFormatHashTable;
  236.                              var WHash : TWidthHashTable;
  237.                              GetColWidth : GetColWidthFunc;
  238.                              CPos : CellPos; FormulasDisplayed : Boolean;
  239.                              Start : Word; ColWidth : Byte;
  240.                              var CurrencyString : CurrencyStr;
  241.                              var ClType: CellTypes): String; virtual;
  242.     function CopyString : String; virtual;
  243.   end; {...TCell }
  244.  
  245.   PEmptyCell = ^TEmptyCell;
  246.   TEmptyCell = OBJECT(TCell)
  247.   { A TCell's descendant that is used to display all empty and/or overwritten
  248.     cells.  Only one instance is TEmptyCell is constructed for use by the
  249.     TSpreadSheet object }
  250.     constructor Init;
  251.     function CellType : CellTypes; virtual;
  252.     function LegalValue : Boolean; virtual;
  253.     function Name : String; virtual;
  254.     function Format(var FHash : TFormatHashTable;
  255.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  256.     function Width(var FHash : TFormatHashTable;
  257.                    FormulasDisplayed : Boolean) : Word; virtual;
  258.     function Overwritten(var CHash : TCellHashTable;
  259.                          var FHash : TFormatHashTable;
  260.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  261.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  262.                          FormulasDisplayed : Boolean) : Word; virtual;
  263.     function ShouldUpdate : Boolean; virtual;
  264.     function HasError : Boolean; virtual;
  265.     function CurrValue : Extended; virtual;
  266.     function OverwriteStart(var FHash : TFormatHashTable;
  267.                             var WHash : TWidthHashTable;
  268.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  269.                             DisplayFormulas : Boolean) : Word; virtual;
  270.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  271.     function DisplayString(FormulasDisplayed : Boolean;
  272.                            MaxDecPlaces : Byte) : String; virtual;
  273.     function FormattedString(var OHash : TOverWriteHashTable;
  274.                              var FHash : TFormatHashTable;
  275.                              var WHash : TWidthHashTable;
  276.                              GetColWidth : GetColWidthFunc;
  277.                              CPos : CellPos; FormulasDisplayed : Boolean;
  278.                              Start : Word; ColWidth : Byte;
  279.                              var CurrencyString : CurrencyStr;
  280.                              var ClType: CellTypes): String; virtual;
  281.     function CopyString : String; virtual;
  282.   end; {..TEmptyCell }
  283.  
  284.   PValueCell = ^TValueCell;
  285.   TValueCell = OBJECT(TCell)
  286.   { A TCell's descendant that stores a number }
  287.        Error : Boolean;
  288.        Value : Extended;
  289.     constructor Init(InitLoc : CellPos; InitError : Boolean;
  290.                      InitValue : Extended);
  291.     function CellType : CellTypes; virtual;
  292.     function LegalValue : Boolean; virtual;
  293.     function Name : String; virtual;
  294.     function Format(var FHash : TFormatHashTable;
  295.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  296.     function Width(var FHash : TFormatHashTable;
  297.                    FormulasDisplayed : Boolean) : Word; virtual;
  298.     function Overwritten(var CHash : TCellHashTable;
  299.                          var FHash : TFormatHashTable;
  300.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  301.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  302.                          FormulasDisplayed : Boolean) : Word; virtual;
  303.     function ShouldUpdate : Boolean; virtual;
  304.     function HasError : Boolean; virtual;
  305.     function CurrValue : Extended; virtual;
  306.     function OverwriteStart(var FHash : TFormatHashTable;
  307.                             var WHash : TWidthHashTable;
  308.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  309.                             DisplayFormulas : Boolean) : Word; virtual;
  310.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  311.     function DisplayString(FormulasDisplayed : Boolean;
  312.                            MaxDecPlaces : Byte) : String; virtual;
  313.     function FormattedString(var OHash : TOverWriteHashTable;
  314.                              var FHash : TFormatHashTable;
  315.                              var WHash : TWidthHashTable;
  316.                              GetColWidth : GetColWidthFunc;
  317.                              CPos : CellPos; FormulasDisplayed : Boolean;
  318.                              Start : Word; ColWidth : Byte;
  319.                              var CurrencyString : CurrencyStr;
  320.                              var ClType: CellTypes): String; virtual;
  321.     function CopyString : String; virtual;
  322.     constructor Load(var S : TStream);
  323.     procedure Store(var S : TStream);
  324.   end; {...TValueCell }
  325.  
  326.   PTextCell = ^TTextCell;
  327.   TTextCell = OBJECT(TCell)
  328.   { A TCell's descendant that stores strings }
  329.       Txt : LString;
  330.     constructor Init(InitLoc : CellPos; InitTxt : String);
  331.     function CellType : CellTypes; virtual;
  332.     function LegalValue : Boolean; virtual;
  333.     function Name : String; virtual;
  334.     function Format(var FHash : TFormatHashTable;
  335.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  336.     function Width(var FHash : TFormatHashTable;
  337.                    FormulasDisplayed : Boolean) : Word; virtual;
  338.     function Overwritten(var CHash : TCellHashTable;
  339.                          var FHash : TFormatHashTable;
  340.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  341.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  342.                          FormulasDisplayed : Boolean) : Word; virtual;
  343.     function ShouldUpdate : Boolean; virtual;
  344.     function HasError : Boolean; virtual;
  345.     function CurrValue : Extended; virtual;
  346.     function OverwriteStart(var FHash : TFormatHashTable;
  347.                             var WHash : TWidthHashTable;
  348.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  349.                             DisplayFormulas : Boolean) : Word; virtual;
  350.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  351.     function DisplayString(FormulasDisplayed : Boolean;
  352.                            MaxDecPlaces : Byte) : String; virtual;
  353.     function FormattedString(var OHash : TOverWriteHashTable;
  354.                              var FHash : TFormatHashTable;
  355.                              var WHash : TWidthHashTable;
  356.                              GetColWidth : GetColWidthFunc;
  357.                              CPos : CellPos; FormulasDisplayed : Boolean;
  358.                              Start : Word; ColWidth : Byte;
  359.                              var CurrencyString : CurrencyStr;
  360.                              var ClType: CellTypes): String; virtual;
  361.     function CopyString : String; virtual;
  362.     constructor Load(var S : TStream);
  363.     procedure Store(var S : TStream);
  364.     destructor Done; virtual;
  365.   end; {...TTextCell }
  366.  
  367.   PFormulaCell = ^TFormulaCell;
  368.   TFormulaCell = OBJECT(TCell)
  369.   { A TCell's descendant that stores a formula and its result.  Since the
  370.     result is a number, TFormulaCell also has all the functionality of a
  371.     TValueCell object }
  372.       Error : Boolean;
  373.       Value : Extended;
  374.       Formula : LString;
  375.     constructor Init(InitLoc : CellPos; InitError : Boolean;
  376.                      InitValue : Extended; InitFormula : String);
  377.     function CellType : CellTypes; virtual;
  378.     function LegalValue : Boolean; virtual;
  379.     function Name : String; virtual;
  380.     function Format(var FHash : TFormatHashTable;
  381.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  382.     function Width(var FHash : TFormatHashTable;
  383.                    FormulasDisplayed : Boolean) : Word; virtual;
  384.     function Overwritten(var CHash : TCellHashTable;
  385.                          var FHash : TFormatHashTable;
  386.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  387.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  388.                          FormulasDisplayed : Boolean) : Word; virtual;
  389.     function ShouldUpdate : Boolean; virtual;
  390.     function HasError : Boolean; virtual;
  391.     function CurrValue : Extended; virtual;
  392.     function OverwriteStart(var FHash : TFormatHashTable;
  393.                             var WHash : TWidthHashTable;
  394.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  395.                             DisplayFormulas : Boolean) : Word; virtual;
  396.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  397.     function DisplayString(FormulasDisplayed : Boolean;
  398.                            MaxDecPlaces : Byte) : String; virtual;
  399.     function FormattedString(var OHash : TOverWriteHashTable;
  400.                              var FHash : TFormatHashTable;
  401.                              var WHash : TWidthHashTable;
  402.                              GetColWidth : GetColWidthFunc;
  403.                              CPos : CellPos; FormulasDisplayed : Boolean;
  404.                              Start : Word; ColWidth : Byte;
  405.                              var CurrencyString : CurrencyStr;
  406.                              var ClType: CellTypes): String; virtual;
  407.     function CopyString : String; virtual;
  408.     constructor Load(var S : TStream);
  409.     procedure Store(var S : TStream);
  410.     function GetFormula : String;
  411.     destructor Done; virtual;
  412.   end; {...TFormulaCell }
  413.  
  414.   PRepeatCell = ^TRepeatCell;
  415.   TRepeatCell = OBJECT(TCell)
  416.   { A TCell's descendant that stores a character that will be repeated
  417.     in all the cell when displayed }
  418.       RepeatChar : Char;
  419.     constructor Init(InitLoc : CellPos; InitChar : Char);
  420.     function CellType : CellTypes; virtual;
  421.     function LegalValue : Boolean; virtual;
  422.     function Name : String; virtual;
  423.     function Format(var FHash : TFormatHashTable;
  424.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  425.     function Width(var FHash : TFormatHashTable;
  426.                    FormulasDisplayed : Boolean) : Word; virtual;
  427.     function Overwritten(var CHash : TCellHashTable;
  428.                          var FHash : TFormatHashTable;
  429.                          var WHash : TWidthHashTable; var LastPos : CellPos;
  430.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  431.                          FormulasDisplayed : Boolean) : Word; virtual;
  432.     function ShouldUpdate : Boolean; virtual;
  433.     function HasError : Boolean; virtual;
  434.     function CurrValue : Extended; virtual;
  435.     function OverwriteStart(var FHash : TFormatHashTable;
  436.                             var WHash : TWidthHashTable;
  437.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  438.                             DisplayFormulas : Boolean) : Word; virtual;
  439.     procedure EditString(MaxDecPlaces : Byte; var Input : String); virtual;
  440.     function DisplayString(FormulasDisplayed : Boolean;
  441.                            MaxDecPlaces : Byte) : String; virtual;
  442.     function FormattedString(var OHash : TOverWriteHashTable;
  443.                              var FHash : TFormatHashTable;
  444.                              var WHash : TWidthHashTable;
  445.                              GetColWidth : GetColWidthFunc;
  446.                              CPos : CellPos; FormulasDisplayed : Boolean;
  447.                              Start : Word; ColWidth : Byte;
  448.                              var CurrencyString : CurrencyStr;
  449.                              var ClType: CellTypes): String; virtual;
  450.     function CopyString : String; virtual;
  451.     constructor Load(var S : TStream);
  452.     procedure Store(var S : TStream);
  453.   end; {...TRepeatCell }
  454.  
  455. type
  456.   FormulaOps = (opInsert, opDelete);
  457.   { Used to indicate the operation that caused a cell address in a
  458.     formula to change.  If a column or a row was inserted then
  459.     the column or row values in affected cell addresses must be
  460.     increased to reflect the change; if a column or a row was
  461.     deleted then the column or row values in affected cell addresses
  462.     must be decreased to reflect the change }
  463.  
  464. var
  465.   Empty : PCell;
  466.   { This is a special cell.  It is used as the return value if a cell
  467.     cannot be found so that the TEmptyCell methods can be executed instead
  468.     of having special routines that act differently depending on whether a
  469.     cell is found ot not. }
  470.  
  471. const
  472.  
  473.   { Stream registration records for the object types that will be written
  474.     to and read from the stream.  }
  475.  
  476.   RValueCell: TStreamRec = (
  477.     ObjType: stRValueCell;
  478.     VmtLink: Ofs(TypeOf(TValueCell)^);
  479.     Load: @TValueCell.Load;
  480.     Store: @TValueCell.Store
  481.   );
  482.  
  483.   RTextCell: TStreamRec = (
  484.     ObjType: stRTextCell;
  485.     VmtLink: Ofs(TypeOf(TTextCell)^);
  486.     Load: @TTextCell.Load;
  487.     Store: @TTextCell.Store
  488.   );
  489.  
  490.   RFormulaCell: TStreamRec = (
  491.     ObjType: stRFormulaCell;
  492.     VmtLink: Ofs(TypeOf(TFormulaCell)^);
  493.     Load: @TFormulaCell.Load;
  494.     Store: @TFormulaCell.Store
  495.   );
  496.  
  497.   RRepeatCell: TStreamRec = (
  498.     ObjType: stRRepeatCell;
  499.     VmtLink: Ofs(TypeOf(TRepeatCell)^);
  500.     Load: @TRepeatCell.Load;
  501.     Store: @TRepeatCell.Store
  502.   );
  503.  
  504. function FormulaStart(Inp : String; Start, MaxCols, MaxRows : Word;
  505.                       var P : CellPos; var FormLen : Word) : Boolean;
  506. { Checks to see if a place in a string is the beginning of a formula }
  507.  
  508. procedure FixFormulaCol(CP : PCell; Operation: FormulaOps; After: Word;
  509.                         Diff : Longint; MaxCols, MaxRows : Word);
  510. { Modify the column references of cell addresses in a formula, to reflect a
  511.   change in position }
  512.  
  513. procedure FixFormulaRow(CP : PCell; Operation: FormulaOps; After: Word;
  514.                         Diff : Longint; MaxCols, MaxRows : Word);
  515. { Modify the row references of cell addresses in a formula, to reflect a
  516.   change in position }
  517.  
  518. procedure RegisterGLCell;
  519. { Register the unit's objects }
  520.  
  521.  
  522. {****************************************************************************}
  523.                                implementation
  524. {****************************************************************************}
  525.  
  526. uses App, Memory;
  527.  
  528. var
  529.   SavedExitProc : Pointer;
  530.  
  531.  
  532. {** Unit's Register Procedures **}
  533.  
  534. procedure RegisterGLCell;
  535. { Registers the different cell types so that they will be written out
  536.   correctly to disk }
  537. begin
  538.   RegisterType(RValueCell);
  539.   RegisterType(RTextCell);
  540.   RegisterType(RFormulaCell);
  541.   RegisterType(RRepeatCell);
  542. end; { RegisterGLCell }
  543.  
  544.  
  545. {** FormulaStart function **}
  546.  
  547. function FormulaStart(Inp : String; Start, MaxCols, MaxRows : Word;
  548.                       var P : CellPos; var FormLen : Word) : Boolean;
  549. { Checks to see if a place in a string is the beginning of a formula }
  550. var
  551.   Col, Row : Word;
  552.   CS : String[10];
  553.   RS : String[10];
  554. begin
  555.    FormulaStart := False;
  556.    FormLen := 0;
  557.    FillChar(P, SizeOf(P), 0);
  558.    CS := '';
  559.    while (Start <= Length(Inp)) and (Inp[Start] in Letters) do
  560.    begin
  561.      CS := CS + Inp[Start];
  562.      Inc(Start);
  563.    end;
  564.    Col := StringToCol(CS, MaxCols);
  565.    if Col = 0 then
  566.      Exit;
  567.    RS := '';
  568.    while (Start <= Length(Inp)) and (Inp[Start] in Numbers) do
  569.    begin
  570.      RS := RS + Inp[Start];
  571.      Inc(Start);
  572.    end;
  573.    Row := StringToRow(RS, MaxRows);
  574.    if Row = 0 then
  575.      Exit;
  576.    P.Col := Col;
  577.    P.Row := Row;
  578.    FormLen := System.Length(CS) + System.Length(RS);
  579.    FormulaStart := True;
  580. end; {...FormulaStart }
  581.  
  582.  
  583. {** FixFormulaCol procedure **}
  584.  
  585. procedure FixFormulaCol(CP : PCell; Operation: FormulaOps; After: Word;
  586.                         Diff : Longint; MaxCols, MaxRows : Word);
  587. var
  588.   FormLen, Place, OldLen, NewLen : Word;
  589.   P : CellPos;
  590.   S : String[10];
  591.   Good : Boolean;
  592.   FormulaStr: String;
  593. begin
  594.   with PFormulaCell(CP)^ do
  595.   begin
  596.     FormulaStr := GetFormula;
  597.     Place := 1;
  598.     while (Place <= Length(FormulaStr)) do
  599.     begin
  600.       if FormulaStart(FormulaStr, Place, MaxCols, MaxRows, P, FormLen) then
  601.       begin
  602.         if (Operation = opInsert) then
  603.            begin
  604.               if (P.Col + Diff) > MaxCols then
  605.                  S := '!REF'
  606.               else if (P.Col >= After) then
  607.                  S := ColToString(LongInt(P.Col) + Diff)
  608.               else
  609.                  S := ColToString(LongInt(P.Col));
  610.            end
  611.         else
  612.            begin
  613.               if (P.Col >= Succ(After - Diff)) and (P.Col <= After) then
  614.                  S := '!REF'
  615.               else if (P.Col > After) then
  616.                  S := ColToString(LongInt(P.Col) - Diff)
  617.               else
  618.                  S := ColToString(LongInt(P.Col));
  619.         end;
  620.         OldLen := Length(ColToString(P.Col));
  621.         NewLen := Length(S);
  622.         if S = '!REF' then
  623.            begin
  624.               Delete(FormulaStr, Place, FormLen);
  625.               Insert(S, FormulaStr, Place);
  626.               Inc(Place, FormLen);
  627.               Good := False;
  628.            end
  629.         else if NewLen > OldLen then
  630.            Insert(FillString(NewLen - OldLen, ' '), FormulaStr, Place)
  631.         else if NewLen < OldLen then
  632.            Delete(FormulaStr, Place, OldLen - NewLen);
  633.         if Good then
  634.         begin
  635.            Move(S[1], FormulaStr[Place], Length(S));
  636.            Inc(Place, FormLen + NewLen - OldLen);
  637.         end;
  638.         Good := True;
  639.       end
  640.       else
  641.         Inc(Place);
  642.     end;
  643.     Formula.Done;
  644.     Formula.Init;
  645.     Formula.FromString(FormulaStr);
  646.   end;
  647. end;
  648.  
  649.  
  650. {** FixFormulaRow procedure **}
  651.  
  652. procedure FixFormulaRow(CP : PCell; Operation: FormulaOps; After: Word;
  653.                         Diff : Longint; MaxCols, MaxRows : Word);
  654. var
  655.   ColLen,FormLen, Place, OldLen, NewLen : Word;
  656.   P : CellPos;
  657.   S : String[10];
  658.   Good : Boolean;
  659.   FormulaStr: String;
  660. begin
  661.   with PFormulaCell(CP)^ do
  662.   begin
  663.     FormulaStr := GetFormula;
  664.     Place := 1;
  665.     while (Place <= Length(FormulaStr)) do
  666.     begin
  667.       if FormulaStart(FormulaStr, Place, MaxCols, MaxRows, P, FormLen) then
  668.       begin
  669.         if (Operation = opInsert) then
  670.            begin
  671.               if (P.Row + Diff) > MaxRows then
  672.                  S := '!REF'
  673.               else if (P.Row >= After) then
  674.                  S := RowToString(LongInt(P.Row) + Diff)
  675.               else
  676.                  S := RowToString(LongInt(P.Row));
  677.            end
  678.         else
  679.            begin
  680.               if ((P.Row >= Succ(After - Diff)) and (P.Row <= After)) then
  681.                  S := '!REF'
  682.               else if (P.Row > After) then
  683.                  S := RowToString(LongInt(P.Row) - Diff)
  684.               else
  685.                  S := RowToString(LongInt(P.Row));
  686.         end;
  687.         OldLen := Length(RowToString(P.Row));
  688.         NewLen := Length(S);
  689.         ColLen := Length(ColToString(P.Col));
  690.         if S = '!REF' then
  691.            begin
  692.               Delete(FormulaStr, Place, FormLen);
  693.               Insert(S, FormulaStr, Place);
  694.               Inc(Place, FormLen);
  695.               Good := False;
  696.            end
  697.         else if NewLen > OldLen then
  698.            Insert(FillString(NewLen - OldLen, ' '), FormulaStr, Place + ColLen)
  699.         else if NewLen < OldLen then
  700.            Delete(FormulaStr, Place + ColLen, OldLen - NewLen);
  701.         if Good then
  702.         begin
  703.            Move(S[1], FormulaStr[Place+ColLen], Length(S));
  704.            Inc(Place, FormLen + NewLen - OldLen);
  705.         end;
  706.         Good := True;
  707.       end
  708.       else
  709.         Inc(Place);
  710.     end;
  711.     Formula.Done;
  712.     Formula.Init;
  713.     Formula.FromString(FormulaStr);
  714.   end;
  715. end;
  716.  
  717.  
  718. {** THashTable **}
  719.  
  720. function THashTable.Add: Boolean;
  721. begin
  722.    if not LowMemory then
  723.       begin
  724.          if not HashTable.Add then
  725.             begin
  726.                Application^.OutOfMemory;
  727.                Add := False;
  728.             end {...if not HashTable.Add }
  729.          else
  730.             Add := True;
  731.       end {...if MemAvail > LowMemoryAddLimit }
  732.    else
  733.       begin
  734.          Application^.OutOfMemory;
  735.          Add := False;
  736.       end; {...else/if MemAvail > LowMemoryAddLimit }
  737. end; {...THashTable.Add }
  738.  
  739.  
  740.  
  741. {** TCellHashTable **}
  742.  
  743. constructor TCellHashTable.Init(InitBuckets : BucketRange);
  744. { Initializes a cell hash table, which stores pointers to the cells in a
  745.   spreadsheet }
  746. begin
  747.   if not THashTable.Init(InitBuckets) then
  748.     Fail;
  749. end; { TCellHashTable.Init }
  750.  
  751. destructor TCellHashTable.Done;
  752. { Removes a cell hash table from memory }
  753. var
  754.   CP : PCell;
  755. begin
  756.   CP := FirstItem;
  757.   while CP <> nil do
  758.   begin
  759.     Dispose(CP, Done);
  760.     CP := NextItem;
  761.   end;
  762.   THashTable.Done;
  763. end; { TCellHashTable.Done }
  764.  
  765. function TCellHashTable.Add(ACell : PCell) : Boolean;
  766. { Adds a cell to a cell hash table }
  767. begin
  768.   CurrCell := ACell;
  769.   CurrLoc := CurrCell^.Loc;
  770.   Add := THashTable.Add;
  771. end; { TCellHashTable.Add }
  772.  
  773. procedure TCellHashTable.Delete(DelLoc : CellPos; var DeletedCell : PCell);
  774. { Deletes a cell from a cell hash table }
  775. begin
  776.   CurrLoc := DelLoc;
  777.   THashTable.Delete(@DeletedCell);
  778. end; { TCellHashTable.Delete }
  779.  
  780. function TCellHashTable.Search(SPos : CellPos) : PCell;
  781. { Searches for a cell in a cell hash table, returning the cell if found, or
  782.   returning the Empty cell if not found }
  783. var
  784.   I : HashItemPtr;
  785.   C : PCell;
  786. begin
  787.   CurrLoc := SPos;
  788.   I := THashTable.Search;
  789.   if I = nil then
  790.     Search := Empty
  791.   else begin
  792.     Move(I^.Data, C, SizeOf(C));
  793.     Search := C;
  794.   end;
  795. end; { TCellHashTable.Search }
  796.  
  797. function TCellHashTable.HashValue : LongInt;
  798. { Calculates the hash value of a cell }
  799. begin
  800.   HashValue := CurrLoc.Col + CurrLoc.Row;
  801. end; { TCellHashTable.HashValue }
  802.  
  803. function TCellHashTable.Found(Item : HashItemPtr) : Boolean;
  804. { Checks to see if a hash item is the one searched for by comparing the
  805.   location information in both }
  806. var
  807.   C : PCell;
  808. begin
  809.   Move(Item^.Data, C, SizeOf(C));
  810.   Found := Compare(C^.Loc, CurrLoc, SizeOf(CurrLoc));
  811. end; { TCellHashTable.Found }
  812.  
  813. procedure TCellHashTable.CreateItem(var Item : HashItemPtr);
  814. { Writes the cell pointer information out to the hash item }
  815. begin
  816.   Move(CurrCell, Item^.Data, SizeOf(CurrCell));
  817. end; { TCellHashTable.CreateItem }
  818.  
  819. function TCellHashTable.ItemSize : HashItemSizeRange;
  820. { The hash item size is current - just cell pointers are stored }
  821. begin
  822.   ItemSize := SizeOf(CurrCell);
  823. end; { TCellHashTable.ItemSize }
  824.  
  825. procedure TCellHashTable.Load(var S : TStream; Total : Longint;
  826.   AdjustAfter: CellPos; RowAdjustment, ColAdjustment: Integer);
  827. { Loads a cell hash table from disk }
  828. var
  829.   Counter : Longint;
  830.   LoadedCell : PCell;
  831. begin
  832.   if AdjustAfter.Col = 0 then
  833.     AdjustAfter.Col := 65535;
  834.   if AdjustAfter.Row = 0 then
  835.     AdjustAfter.Row := 65535;
  836.   for Counter := 1 to Total do
  837.   begin
  838.     LoadedCell := PCell(S.Get);
  839.     if LoadedCell^.Loc.Col >= AdjustAfter.Col then
  840.       Inc(LoadedCell^.Loc.Col, ColAdjustment);
  841.     if LoadedCell^.Loc.Row >= AdjustAfter.Row then
  842.       Inc(LoadedCell^.Loc.Row, RowAdjustment);
  843.     if not Add(LoadedCell) then
  844.     begin
  845.       if CurrCell <> NIL then
  846.          Dispose(CurrCell, Done);
  847.       S.Error(stNoMemoryError, 0);
  848.       Exit;
  849.     end;
  850.   end;
  851. end; { TCellHashTable.Load }
  852.  
  853. procedure TCellHashTable.Store(var S : TStream);
  854. { Writes a cell hash table to disk }
  855. var
  856.   CP : PCell;
  857. begin
  858.   CP := FirstItem;
  859.   while CP <> nil do
  860.   begin
  861.     S.Put(CP);
  862.     CP := NextItem;
  863.   end;
  864. end; { TCellHashTable.Store }
  865.  
  866. function HashItemPtrToCellPtr(H : HashItemPtr) : PCell;
  867. { Converts a hash item pointer to a cell pointer }
  868. var
  869.   CP : PCell;
  870. begin
  871.   if H = nil then
  872.     HashItemPtrToCellPtr := nil
  873.   else begin
  874.     Move(H^.Data, CP, SizeOf(CP));
  875.     HashItemPtrToCellPtr := CP;
  876.   end;
  877. end; { HashItemPtrToCellPtr }
  878.  
  879. function TCellHashTable.FirstItem : PCell;
  880. { Returns the first hash item in a cell hash table }
  881. begin
  882.   FirstItem := HashItemPtrToCellPtr(THashTable.FirstItem);
  883. end; { TCellHashTable.FirstItem }
  884.  
  885. function TCellHashTable.NextItem : PCell;
  886. { Returns the second and subsequent hash items in a cell hash table }
  887. begin
  888.   NextItem := HashItemPtrToCellPtr(THashTable.NextItem);
  889. end; { TCellHashTable.NextItem }
  890.  
  891.  
  892.  
  893. {** TWidthHashTable **}
  894.  
  895. constructor TWidthHashTable.Init(InitBuckets : BucketRange;
  896.                                 InitDefaultColWidth : Byte);
  897. { Initializes the width hash table, which stores column widths that are
  898.   different than the default.  It stores the column and the width in the
  899.   hash table }
  900. begin
  901.   if not THashTable.Init(InitBuckets) then
  902.     Fail;
  903.   DefaultColWidth := InitDefaultColWidth;
  904. end; { TWidthHashTable.Init }
  905.  
  906. destructor TWidthHashTable.Done;
  907. begin
  908.   THashTable.Done;
  909. end; { TWidthHashTable.Done }
  910.  
  911. function TWidthHashTable.Add(SCol : Word; NewWidth : Byte) : Boolean;
  912. begin
  913.   CurrCol := SCol;
  914.   CurrWidth := NewWidth;
  915.   Add := THashTable.Add;
  916. end; { TWidthHashTable }
  917.  
  918. procedure TWidthHashTable.Delete(Col : Word);
  919. begin
  920.   CurrCol := Col;
  921.   THashTable.Delete(nil);
  922. end; { TWidthHashTable.Delete }
  923.  
  924. function TWidthHashTable.Search(Col : Word) : Byte;
  925. var
  926.   I : HashItemPtr;
  927.   W : Byte;
  928. begin
  929.   CurrCol := Col;
  930.   I := THashTable.Search;
  931.   if I = nil then
  932.     Search := 0
  933.   else begin
  934.     Move(I^.Data[SizeOf(CurrCol)], W, SizeOf(W));
  935.     Search := W;
  936.   end;
  937. end; { TWidthHashTable.Search }
  938.  
  939. function TWidthHashTable.HashValue : LongInt;
  940. begin
  941.   HashValue := CurrCol;
  942. end; { TWidthHashTable.HashValue }
  943.  
  944. function TWidthHashTable.Found(Item : HashItemPtr) : Boolean;
  945. var
  946.   C : Word;
  947. begin
  948.   Move(Item^.Data, C, SizeOf(C));
  949.   Found := CurrCol = C;
  950. end; { TWidthHashTable.Found }
  951.  
  952. procedure TWidthHashTable.CreateItem(var Item : HashItemPtr);
  953. begin
  954.   Move(CurrCol, Item^.Data, SizeOf(CurrCol));
  955.   Move(CurrWidth, Item^.Data[SizeOf(CurrCol)], SizeOf(CurrWidth));
  956. end; { TWidthHashTable.CreateItem }
  957.  
  958. function TWidthHashTable.ItemSize : HashItemSizeRange;
  959. begin
  960.   ItemSize := SizeOf(CurrCol) + SizeOf(CurrWidth);
  961. end; { TWidthHashTable.ItemSize }
  962.  
  963. function TWidthHashTable.GetDefaultColWidth : Byte;
  964. begin
  965.   GetDefaultColWidth := DefaultColWidth;
  966. end; { TWidthHashTable.GetDefaultColWidth }
  967.  
  968. procedure TWidthHashTable.Load(var S : TStream; Total : Longint);
  969. var
  970.   Counter : Longint;
  971.   Col : Word;
  972.   Width : Byte;
  973. begin
  974.   for Counter := 1 to Total do
  975.   begin
  976.     S.Read(Col, SizeOf(Col));
  977.     S.Read(Width, SizeOf(Width));
  978.     if not Add(Col, Width) then
  979.     begin
  980.       S.Error(stNoMemoryError, 0);
  981.       Exit;
  982.     end;
  983.   end;
  984. end; { TWidthHashTable.Load }
  985.  
  986. procedure TWidthHashTable.Store(var S : TStream);
  987. var
  988.   H : HashItemPtr;
  989.   Col : Word;
  990.   Width : Byte;
  991. begin
  992.   H := FirstItem;
  993.   while H <> nil do
  994.   begin
  995.     Move(H^.Data, Col, SizeOf(Col));
  996.     S.Write(Col, SizeOf(Col));
  997.     Move(H^.Data[SizeOf(Col)], Width, SizeOf(Width));
  998.     S.Write(Width, SizeOf(Width));
  999.     H := NextItem;
  1000.   end;
  1001. end; { TWidthHashTable.Store }
  1002.  
  1003.  
  1004.  
  1005. {** TFormatHashTable **}
  1006.  
  1007. constructor TFormatHashTable.Init;
  1008. { Initializes a format hash table, which is used to store formatted areas
  1009.   that differ from the default.  The area and the format are stored in the
  1010.   hash table }
  1011. begin
  1012.   if not THashTable.Init(1) then   { Use a single bucket so that a search }
  1013.     Fail;                          { will be possible }
  1014. end; { TFormatHashTable.Init }
  1015.  
  1016. destructor TFormatHashTable.Done;
  1017. begin
  1018.   THashTable.Done;
  1019. end; { TFormatHashTable.Done }
  1020.  
  1021. function TFormatHashTable.Overwrite(NewStart, NewStop : CellPos) : Boolean;
  1022. { Checks to see if a new format area has overwritten an old one, requiring
  1023.   the old area to be overwritten or broken into parts }
  1024. var
  1025.   H, Next : HashItemPtr;
  1026.   AStart, AStop, BStart, BStop : CellPos;
  1027.   F : FormatType;
  1028.   P : CellPos;
  1029.   Added : Boolean;
  1030. begin
  1031.   Overwrite := False;
  1032.   H := HashData^[1];
  1033.   while H <> nil do
  1034.   begin
  1035.     Next := H^.Next;
  1036.     Move(H^.Data, BStart, SizeOf(CellPos));
  1037.     Move(H^.Data[SizeOf(CellPos)], BStop, SizeOf(CellPos));
  1038.     if ((((NewStart.Col >= BStart.Col) and (NewStart.Col <= BStop.Col)) or
  1039.          ((NewStop.Col >= BStart.Col) and (NewStop.Col <= BStop.Col))) and
  1040.         (((NewStart.Row >= BStart.Row) and (NewStart.Row <= BStop.Row)) or
  1041.          ((NewStop.Row >= BStart.Row) and (NewStop.Row <= BStop.Row)))) or
  1042.        ((((BStart.Col >= NewStart.Col) and (BStart.Col <= NewStop.Col)) or
  1043.          ((BStop.Col >= NewStart.Col) and (BStop.Col <= NewStop.Col))) and
  1044.         (((BStart.Row >= NewStart.Row) and (BStart.Row <= NewStop.Row)) or
  1045.          ((BStop.Row >= NewStart.Row) and (BStop.Row <= NewStop.Row)))) then
  1046.     begin
  1047.       Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
  1048.       CurrStart := BStart;
  1049.       CurrStop := BStop;
  1050.       THashTable.Delete(nil);
  1051.       if BStart.Row < NewStart.Row then
  1052.       begin
  1053.         AStart := BStart;
  1054.         AStop.Col := BStop.Col;
  1055.         AStop.Row := Pred(NewStart.Row);
  1056.         if not Add(AStart, AStop, F) then
  1057.           Exit;
  1058.       end;
  1059.       if BStop.Row > NewStop.Row then
  1060.       begin
  1061.         AStart.Col := BStart.Col;
  1062.         AStart.Row := Succ(NewStop.Row);
  1063.         AStop.Col := BStop.Col;
  1064.         AStop.Row := BStop.Row;
  1065.         if not Add(AStart, AStop, F) then
  1066.           Exit;
  1067.       end;
  1068.       if BStart.Col < NewStart.Col then
  1069.       begin
  1070.         AStart.Col := BStart.Col;
  1071.         AStart.Row := Max(BStart.Row, NewStart.Row);
  1072.         AStop.Col := Pred(NewStart.Col);
  1073.         AStop.Row := Min(BStop.Row, NewStop.Row);
  1074.         if not Add(AStart, AStop, F) then
  1075.           Exit;
  1076.       end;
  1077.       if BStop.Col > NewStop.Col then
  1078.       begin
  1079.         AStart.Col := Succ(NewStop.Col);
  1080.         AStart.Row := Max(BStart.Row, NewStart.Row);
  1081.         AStop.Col := BStop.Col;
  1082.         AStop.Row := Min(BStop.Row, NewStop.Row);
  1083.         if not Add(AStart, AStop, F) then
  1084.           Exit;
  1085.       end;
  1086.     end;
  1087.     H := Next;
  1088.   end;
  1089.   Overwrite := True;
  1090. end; { TFormatHashTable.Overwrite }
  1091.  
  1092. function TFormatHashTable.Add(NewStart, NewStop : CellPos;
  1093.                              NewFormat : FormatType) : Boolean;
  1094. begin
  1095.   if not Overwrite(NewStart, NewStop) then
  1096.   begin
  1097.     Add := False;
  1098.     Exit;
  1099.   end;
  1100.   CurrStart := NewStart;
  1101.   CurrStop := NewStop;
  1102.   CurrFormat := NewFormat;
  1103.   Add := THashTable.Add;
  1104. end; { TFormatHashTable.Add }
  1105.  
  1106. function TFormatHashTable.Delete(DStart, DStop : CellPos) : Boolean;
  1107. begin
  1108.   Delete := Overwrite(DStart, DStop);
  1109. end; { TFormatHashTable.Delete }
  1110.  
  1111. function TFormatHashTable.Search(SPos : CellPos; var F : FormatType) :
  1112.                                  Boolean;
  1113. var
  1114.   H : HashItemPtr;
  1115. begin
  1116.   CurrStart := SPos;
  1117.   H := THashTable.Search;
  1118.   if H = nil then
  1119.     Search := False
  1120.   else begin
  1121.     Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
  1122.     Search := True;
  1123.   end;
  1124. end; { TFormatHashTable.Search }
  1125.  
  1126. function TFormatHashTable.HashValue : LongInt;
  1127. { Since the hash table has only one bucket, the hash value is always 1 }
  1128. begin
  1129.   HashValue := 1;
  1130. end; { TFormatHashTable.HashValue }
  1131.  
  1132. function TFormatHashTable.Found(Item : HashItemPtr) : Boolean;
  1133. var
  1134.   P : CellPos;
  1135.   B : TBlock;
  1136.   Start, Stop : CellPos;
  1137.   Good : Boolean;
  1138. begin
  1139.   Move(Item^.Data, Start, SizeOf(CellPos));
  1140.   Move(Item^.Data[SizeOf(CellPos)], Stop, SizeOf(CellPos));
  1141.   B.Init(Start);
  1142.   B.Stop := Stop;
  1143.   Found := B.CellInBlock(CurrStart);
  1144. end; { TFormatHashTable.Found }
  1145.  
  1146. procedure TFormatHashTable.CreateItem(var Item : HashItemPtr);
  1147. begin
  1148.   with Item^ do
  1149.   begin
  1150.     Move(CurrStart, Data, SizeOf(CellPos));
  1151.     Move(CurrStop, Data[SizeOf(CellPos)], SizeOf(CellPos));
  1152.     Move(CurrFormat, Data[SizeOf(CellPos) shl 1], SizeOf(CurrFormat));
  1153.   end; { with }
  1154. end; { TFormatHashTable.CreateItem }
  1155.  
  1156. function TFormatHashTable.ItemSize : HashItemSizeRange;
  1157. begin
  1158.   ItemSize := (SizeOf(CellPos) shl 1) + SizeOf(FormatType);
  1159. end; { TFormatHashTable.ItemSize }
  1160.  
  1161. procedure TFormatHashTable.Load(var S : TStream; Total : Longint);
  1162. var
  1163.   Counter : Longint;
  1164.   C1, C2 : CellPos;
  1165.   Format : FormatType;
  1166. begin
  1167.   for Counter := 1 to Total do
  1168.   begin
  1169.     S.Read(C1, SizeOf(C1));
  1170.     S.Read(C2, SizeOf(C2));
  1171.     S.Read(Format, 2);
  1172.     if not Add(C1, C2, Format) then
  1173.     begin
  1174.       S.Error(stNoMemoryError, 0);
  1175.       Exit;
  1176.     end;
  1177.   end;
  1178. end; { TFormatHashTable.Load }
  1179.  
  1180. procedure TFormatHashTable.Store(var S : TStream);
  1181. var
  1182.   H : HashItemPtr;
  1183.   C : CellPos;
  1184.   Format : Byte;
  1185. begin
  1186.   H := FirstItem;
  1187.   while H <> nil do
  1188.   begin
  1189.     Move(H^.Data, C, SizeOf(C));
  1190.     S.Write(C, SizeOf(C));
  1191.     Move(H^.Data[SizeOf(CellPos)], C, SizeOf(C));
  1192.     S.Write(C, SizeOf(C));
  1193.     Move(H^.Data[SizeOf(CellPos) shl 1], Format, 2);
  1194.     S.Write(Format, 2);
  1195.     H := NextItem;
  1196.   end;
  1197. end; { TFormatHashTable.Store }
  1198.  
  1199.  
  1200.  
  1201. {** TOverWriteHashTable **}
  1202.  
  1203. constructor TOverWriteHashTable.Init(InitBuckets : BucketRange);
  1204. { Initializes an overwrite hash table, which keeps track of which cells are
  1205.   overwritten by other cells }
  1206. begin
  1207.   if not THashTable.Init(InitBuckets) then
  1208.     Fail;
  1209. end; { TOverWriteHashTable.Init }
  1210.  
  1211. destructor TOverWriteHashTable.Done;
  1212. begin
  1213.   THashTable.Done;
  1214. end; { TOverWriteHashTable.Done }
  1215.  
  1216. function TOverWriteHashTable.Add(SCell : PCell;
  1217.                                  var CHash: TCellHashTable;
  1218.                                  var FHash: TFormatHashTable;
  1219.                                  var WHash: TWidthHashTable; LastPos: CellPos;
  1220.                                  MaxCols: Word; GetColWidth: GetColWidthFunc;
  1221.                                  FormulasDisplayed, ChangeYes: Boolean)
  1222.                                  : Boolean;
  1223. var
  1224.   CP : PCell;
  1225.   NewOverWritten, OverWritten : Word;
  1226.  
  1227. const
  1228.   ChangeNo = False;
  1229.  
  1230. begin
  1231.   if ChangeYes then
  1232.   begin
  1233.      CP := Search(SCell^.Loc);
  1234.      if CP <> Empty then
  1235.      begin
  1236.        NewOverWritten := CP^.OverWritten(CHash, FHash, WHash, LastPos,
  1237.                              MaxCols, GetColWidth, FormulasDisplayed);
  1238.        if NewOverWritten = 0 then
  1239.              Delete(CP^.Loc, CHash, FHash, WHash, LastPos, MaxCols,
  1240.                     GetColWidth, FormulasDisplayed, ChangeNo)
  1241.        else if (not Change(CP, NewOverWritten)) then
  1242.        begin
  1243.          Add := False;
  1244.          Exit;
  1245.        end; {...else if not Change(CP, CP^.OverWritten) }
  1246.      end; {...if CP <> Empty }
  1247.   end; {...if ChangeYes}
  1248.   OverWritten := SCell^.Overwritten(CHash, FHash, WHash, LastPos, MaxCols, GetColWidth,
  1249.                         FormulasDisplayed);
  1250.   if OverWritten = 0 then
  1251.      Add := True
  1252.   else
  1253.      begin
  1254.         CurrCell := SCell;
  1255.         CurrPos := SCell^.Loc;
  1256.         EndCol := CurrPos.Col + Overwritten;
  1257.         Add := THashTable.Add;
  1258.      end; {...else/if OverWritten = 0 }
  1259. end; {...TOverWriteHashTable.Add }
  1260.  
  1261. procedure TOverWriteHashTable.Delete(SPos : CellPos;
  1262.                                  var CHash: TCellHashTable;
  1263.                                  var FHash: TFormatHashTable;
  1264.                                  var WHash: TWidthHashTable; LastPos: CellPos;
  1265.                                  MaxCols: Word; GetColWidth: GetColWidthFunc;
  1266.                                  FormulasDisplayed, ChangeYes: Boolean);
  1267. var
  1268.    CellPtr : PCell;
  1269.    OverWritten : Word;
  1270. begin
  1271.    CurrPos := SPos;
  1272.    THashTable.Delete(NIL);
  1273.    if ChangeYes and (SPos.Col > 1) then
  1274.    begin
  1275.       Dec(SPos.Col);
  1276.       CellPtr := Search(SPos);
  1277.       if CellPtr = Empty then
  1278.          CellPtr := CHash.Search(SPos);
  1279.       if CellPtr <> Empty then
  1280.       begin
  1281.          OverWritten := CellPtr^.OverWritten(CHash, FHash, WHash, LastPos,
  1282.                                   MaxCols, GetColWidth, FormulasDisplayed);
  1283.          if OverWritten <> 0 then
  1284.             Change(CellPtr, OverWritten);
  1285.       end; {...if CellPtr <> Empty }
  1286.    end; {...if SPos.Col > 1 }
  1287. end; {...TOverWriteHashTable.Delete }
  1288.  
  1289. function TOverWriteHashTable.Change(SCell : PCell;
  1290.                                    Overwritten : Word) : Boolean;
  1291. begin
  1292.    CurrCell := SCell;
  1293.    CurrPos := CurrCell^.Loc;
  1294.    EndCol := SCell^.Loc.Col + Overwritten;
  1295.    Change := THashTable.Change;
  1296. end; {...TOverWriteHashTable.Change }
  1297.  
  1298. function TOverWriteHashTable.Search(SPos : CellPos) : PCell;
  1299. var
  1300.   I : HashItemPtr;
  1301.   C : PCell;
  1302. begin
  1303.   CurrPos := SPos;
  1304.   I := THashTable.Search;
  1305.   if I = nil then
  1306.     Search := Empty
  1307.   else begin
  1308.     Move(I^.Data, C, SizeOf(C));
  1309.     Search := C;
  1310.   end;
  1311. end; { TOverWriteHashTable.Search }
  1312.  
  1313. function TOverWriteHashTable.HashValue : LongInt;
  1314. begin
  1315.   HashValue := CurrPos.Row;
  1316. end; { TOverWriteHashTable.HashValue }
  1317.  
  1318. function TOverWriteHashTable.Found(Item : HashItemPtr) : Boolean;
  1319. var
  1320.   C : PCell;
  1321.   E : Word;
  1322. begin
  1323.   Move(Item^.Data, C, SizeOf(C));
  1324.   Move(Item^.Data[SizeOf(C)], E, SizeOf(E));
  1325.   with CurrPos do
  1326.     Found := (Row = C^.Loc.Row) and (Col >= C^.Loc.Col) and
  1327.              (Col <= E);
  1328. end; { TOverWriteHashTable.Found }
  1329.  
  1330. procedure TOverWriteHashTable.CreateItem(var Item : HashItemPtr);
  1331. begin
  1332.   Move(CurrCell, Item^.Data, SizeOf(CurrCell));
  1333.   Move(EndCol, Item^.Data[SizeOf(CurrCell)], SizeOf(EndCol));
  1334. end; { TOverWriteHashTable.CreateItem }
  1335.  
  1336. function TOverWriteHashTable.ItemSize : HashItemSizeRange;
  1337. begin
  1338.   ItemSize := SizeOf(CurrCell) + SizeOf(EndCol);
  1339. end; { TOverWriteHashTable.ItemSize }
  1340.  
  1341.  
  1342.  
  1343. {** TCell **}
  1344.  
  1345. constructor TCell.Init(InitLoc : CellPos);
  1346. { Initializes a cell's location }
  1347. begin
  1348.   Loc := InitLoc;
  1349. end; { TCell.Init }
  1350.  
  1351. destructor TCell.Done;
  1352. { Frees memory used by the cell }
  1353. begin
  1354. end; { TCell.Done }
  1355.  
  1356. function TCell.CellType : CellTypes;
  1357. { Returns the type of a cell - used in copying cells }
  1358. begin
  1359.   Abstract('TCell.CellType');
  1360. end; { TCell.CellType }
  1361.  
  1362. function TCell.LegalValue : Boolean;
  1363. { Returns True if the cell has a legal numeric value }
  1364. begin
  1365.   Abstract('TCell.LegalValue');
  1366. end; { TCell.LegalValue }
  1367.  
  1368. function TCell.Name : String;
  1369. { Returns the name of the cell type }
  1370. begin
  1371.   Abstract('TCell.Name');
  1372. end; { TCell.Name }
  1373.  
  1374. function TCell.Format(var FHash : TFormatHashTable; FormulasDisplayed : Boolean) :
  1375.                          FormatType;
  1376. { Returns the format of a cell }
  1377. begin
  1378.   Abstract('TCell.Format');
  1379. end; { TCell.Format }
  1380.  
  1381. function TCell.Width(var FHash : TFormatHashTable; FormulasDisplayed : Boolean) :
  1382.                         Word;
  1383. { Returns the width of a cell (including the cells that it will overwrite) }
  1384. begin
  1385.   Abstract('TCell.Width');
  1386. end; { TCell.Width }
  1387.  
  1388. function TCell.Overwritten(var CHash : TCellHashTable;
  1389.                                var FHash : TFormatHashTable;
  1390.                                var WHash : TWidthHashTable;
  1391.                                var LastPos : CellPos;
  1392.                                MaxCols : Word;
  1393.                                GetColWidth : GetColWidthFunc;
  1394.                                FormulasDisplayed : Boolean) : Word;
  1395. { Calculates how many cells a cell will overwrite }
  1396. begin
  1397.   Abstract('TCell.Overwritten');
  1398. end; { TCell.Overwritten }
  1399.  
  1400. function TCell.ShouldUpdate : Boolean;
  1401. { Returns True if the cell needs to be updated when the spreadsheet changes }
  1402. begin
  1403.   Abstract('TCell.ShouldUpdate');
  1404. end; { TCell.ShouldUpdate }
  1405.  
  1406. function TCell.HasError : Boolean;
  1407. { Returns True if the cell has a numeric error in it }
  1408. begin
  1409.   Abstract('TCell.HasError');
  1410. end; { TCell.HasError }
  1411.  
  1412. function TCell.CurrValue : Extended;
  1413. { Returns the current numeric value of a cell }
  1414. begin
  1415.   Abstract('TCell.CurrValue');
  1416. end; { TCell.CurrValue }
  1417.  
  1418. function TCell.OverwriteStart(var FHash : TFormatHashTable;
  1419.                              var WHash : TWidthHashTable;
  1420.                              GetColWidth : GetColWidthFunc; EndCol : Word;
  1421.                              DisplayFormulas : Boolean) : Word;
  1422. { Determines, for overwritten cells, where in the overwriting data they will
  1423.   Start to display a value }
  1424. begin
  1425.   Abstract('TCell.OverwriteStart');
  1426. end; { TCell.OverwriteStart }
  1427.  
  1428. procedure TCell.EditString(MaxDecPlaces : Byte;
  1429.                            var Input : String);
  1430. { Sets up a long string with the cell's value that can be edited }
  1431. begin
  1432.   Abstract('TCell.EditString');
  1433. end; { TCell.EditString }
  1434.  
  1435. function TCell.DisplayString(FormulasDisplayed : Boolean;
  1436.                             MaxDecPlaces : Byte) : String;
  1437. { Returns the string that will be displayed just above the input line }
  1438. begin
  1439.   Abstract('TCell.DisplayString');
  1440. end; { TCell.DisplayString }
  1441.  
  1442. function TCell.FormattedString(var OHash : TOverWriteHashTable;
  1443.                               var FHash : TFormatHashTable;
  1444.                               var WHash : TWidthHashTable;
  1445.                               GetColWidth : GetColWidthFunc;
  1446.                               CPos : CellPos; FormulasDisplayed : Boolean;
  1447.                               Start : Word; ColWidth : Byte;
  1448.                               var CurrencyString : CurrencyStr;
  1449.                               var ClType: CellTypes): String;
  1450. { Returns the string that will be printed in a cell }
  1451. begin
  1452.   Abstract('TCell.FormattedString');
  1453. end; { TCell.FormattedString }
  1454.  
  1455. function TCell.CopyString : String;
  1456. { Copies a cell's string information to another cell's }
  1457. begin
  1458.   Abstract('TCell.CopyString');
  1459. end; { TCell.CopyString }
  1460.  
  1461.  
  1462.  
  1463. {** TEmptyCell **}
  1464.  
  1465. constructor TEmptyCell.Init;
  1466. var
  1467.   NewLoc : CellPos;
  1468. begin
  1469.   NewLoc.Col := 0;
  1470.   NewLoc.Row := 0;
  1471.   TCell.Init(NewLoc);
  1472. end; { TEmptyCell.Init }
  1473.  
  1474. function TEmptyCell.CellType : CellTypes;
  1475. begin
  1476.   CellType := ClEmpty;
  1477. end; { TEmptyCell.CellType }
  1478.  
  1479. function TEmptyCell.LegalValue : Boolean;
  1480. begin
  1481.   LegalValue := True;
  1482. end; { TEmptyCell.LegalValue }
  1483.  
  1484. function TEmptyCell.Name : String;
  1485. begin
  1486.   Name := GLStringList^.Get(sEmptyCellName);
  1487. end; { TEmptyCell.Name }
  1488.  
  1489. function TEmptyCell.Format(var FHash : TFormatHashTable;
  1490.                               FormulasDisplayed : Boolean) : FormatType;
  1491. begin
  1492.   Format := 0;
  1493. end; { TEmptyCell.Format }
  1494.  
  1495. function TEmptyCell.Width(var FHash : TFormatHashTable;
  1496.                              FormulasDisplayed : Boolean) : Word;
  1497. begin
  1498.   Width := 0;
  1499. end; { TEmptyCell.Width }
  1500.  
  1501. function TEmptyCell.Overwritten(var CHash : TCellHashTable;
  1502.                                     var FHash : TFormatHashTable;
  1503.                                     var WHash : TWidthHashTable;
  1504.                                     var LastPos : CellPos;
  1505.                                     MaxCols : Word;
  1506.                                     GetColWidth : GetColWidthFunc;
  1507.                                     FormulasDisplayed : Boolean) : Word;
  1508. begin
  1509.   Overwritten := 0;
  1510. end; { TEmptyCell.Overwritten }
  1511.  
  1512. function TEmptyCell.ShouldUpdate : Boolean;
  1513. begin
  1514.   ShouldUpdate := False;
  1515. end; { TEmptyCell.ShouldUpdate }
  1516.  
  1517. function TEmptyCell.HasError : Boolean;
  1518. begin
  1519.   HasError := False;
  1520. end; { TCell.HasError }
  1521.  
  1522. function TEmptyCell.CurrValue : Extended;
  1523. begin
  1524.   CurrValue := 0;
  1525. end; { TEmptyCell.CurrValue }
  1526.  
  1527. function TEmptyCell.OverwriteStart(var FHash : TFormatHashTable;
  1528.                                   var WHash : TWidthHashTable;
  1529.                                   GetColWidth : GetColWidthFunc;
  1530.                                   EndCol : Word;
  1531.                                   DisplayFormulas : Boolean) : Word;
  1532. begin
  1533.   OverwriteStart := 1;
  1534. end; { TEmptyCell.OverwriteStart }
  1535.  
  1536. procedure TEmptyCell.EditString(MaxDecPlaces : Byte;
  1537.                                      var Input : String);
  1538. begin
  1539.   Input := '';
  1540. end; { TEmptyCell.EditString }
  1541.  
  1542. function TEmptyCell.DisplayString(FormulasDisplayed : Boolean;
  1543.                                        MaxDecPlaces : Byte) : String;
  1544. begin
  1545.   DisplayString := '';
  1546. end; { TEmptyCell.DisplayString }
  1547.  
  1548. function TEmptyCell.FormattedString(var OHash : TOverWriteHashTable;
  1549.                                    var FHash : TFormatHashTable;
  1550.                                    var WHash : TWidthHashTable;
  1551.                                    GetColWidth : GetColWidthFunc;
  1552.                                    CPos : CellPos;
  1553.                                    FormulasDisplayed : Boolean;
  1554.                                    Start : Word; ColWidth : Byte;
  1555.                                    var CurrencyString : CurrencyStr;
  1556.                                    var ClType: CellTypes) : String;
  1557. var
  1558.   CP : PCell;
  1559. begin
  1560.   CP := OHash.Search(CPos);
  1561.   if CP <> Empty then
  1562.     FormattedString := CP^.FormattedString(OHash, FHash, WHash, GetColWidth,
  1563.                                            Loc, FormulasDisplayed,
  1564.                                            CP^.OverWriteStart(FHash, WHash,
  1565.                                            GetColWidth, CPos.Col,
  1566.                                            FormulasDisplayed), ColWidth,
  1567.                                            CurrencyString, ClType)
  1568.   else begin
  1569.     ClType := CellType;
  1570.     FormattedString := '';
  1571.     CurrencyString := '';
  1572.   end;
  1573. end; { TEmptyCell.FormattedString }
  1574.  
  1575. function TEmptyCell.CopyString : String;
  1576. begin
  1577.   CopyString := '';
  1578. end; { TEmptyCell.CopyString }
  1579.  
  1580.  
  1581.  
  1582. {** TValueCell **}
  1583.  
  1584. constructor TValueCell.Init(InitLoc : CellPos; InitError : Boolean;
  1585.                            InitValue : Extended);
  1586. begin
  1587.   TCell.Init(InitLoc);
  1588.   Error := InitError;
  1589.   Value := InitValue;
  1590. end; { TValueCell.Init }
  1591.  
  1592. function TValueCell.CellType : CellTypes;
  1593. begin
  1594.   CellType := ClValue;
  1595. end; { TValueCell.CellType }
  1596.  
  1597. function TValueCell.LegalValue : Boolean;
  1598. begin
  1599.   LegalValue := True;
  1600. end; { TValueCell.LegalValue }
  1601.  
  1602. function TValueCell.Name : String;
  1603. begin
  1604.   Name := GLStringList^.Get(sValueCellName);
  1605. end; { TValueCell.Name }
  1606.  
  1607. function TValueCell.Format(var FHash : TFormatHashTable;
  1608.                               FormulasDisplayed : Boolean) : FormatType;
  1609. var
  1610.   F : FormatType;
  1611. begin
  1612.   if FHash.Search(Loc, F) then
  1613.     Format := F
  1614.   else
  1615.     Format := (Ord(JRight) shl 4) + DefaultDefaultDecimalPlaces;
  1616. end; { TValueCell.Format }
  1617.  
  1618. function TValueCell.Width(var FHash : TFormatHashTable;
  1619.                              FormulasDisplayed : Boolean) : Word;
  1620. var
  1621.   S : String;
  1622.   F : FormatType;
  1623.   P, W : Integer;
  1624. begin
  1625.   F := Format(FHash, FormulasDisplayed);
  1626.   Str(Value:1:(F and DecPlacesPart), S);
  1627.   W := Length(S);
  1628.   if (F and CurrencyPart) <> 0 then
  1629.     Inc(W, Length(DefaultCurrencyString));
  1630.   if (F and CommasPart) <> 0 then
  1631.   begin
  1632.     P := Pos('.', S);
  1633.     if P = 0 then
  1634.       P := Length(S);
  1635.     inc(W, (P - 2) div 3);
  1636.   end;
  1637.   Width := W;
  1638. end; { TValueCell.Width }
  1639.  
  1640. function TValueCell.Overwritten(var CHash : TCellHashTable;
  1641.                                var FHash : TFormatHashTable;
  1642.                                var WHash : TWidthHashTable;
  1643.                                var LastPos : CellPos;
  1644.                                MaxCols : Word;
  1645.                                GetColWidth : GetColWidthFunc;
  1646.                                FormulasDisplayed : Boolean) : Word;
  1647. var
  1648.   CellWidth : Longint;
  1649.   Total : Word;
  1650.   P : CellPos;
  1651. begin
  1652.   P := Loc;
  1653.   CellWidth := Width(FHash, FormulasDisplayed);
  1654.   Total := 0;
  1655.   repeat
  1656.     Inc(Total);
  1657.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  1658.     Inc(P.Col);
  1659.   until (CellWidth <= 0) or (P.Col > MaxCols) or (CHash.Search(P) <> Empty);
  1660.   Dec(Total);
  1661.   Overwritten := Total;
  1662. end; { TValueCell.Overwritten }
  1663.  
  1664. function TValueCell.ShouldUpdate : Boolean;
  1665. begin
  1666.   ShouldUpdate := False;
  1667. end; { TValueCell.ShouldUpdate }
  1668.  
  1669. function TValueCell.HasError : Boolean;
  1670. begin
  1671.   HasError := Error;
  1672. end; { TValueCell.HasError }
  1673.  
  1674. function TValueCell.CurrValue : Extended;
  1675. begin
  1676.   CurrValue := Value;
  1677. end; { TValueCell.CurrValue }
  1678.  
  1679. function TValueCell.OverwriteStart(var FHash : TFormatHashTable;
  1680.                                   var WHash : TWidthHashTable;
  1681.                                   GetColWidth : GetColWidthFunc;
  1682.                                   EndCol : Word;
  1683.                                   DisplayFormulas : Boolean) : Word;
  1684. var
  1685.   F : FormatType;
  1686.   C, Place : Word;
  1687. begin
  1688.   F := Format(FHash, DisplayFormulas);
  1689.   Place := 1;
  1690.   C := Loc.Col;
  1691.   repeat
  1692.     Inc(Place, GetColWidth(WHash, C));
  1693.     Inc(C);
  1694.   until C = EndCol;
  1695.   if (F and CurrencyPart) <> 0 then
  1696.     Dec(Place, Length(DefaultCurrencyString));
  1697.   OverwriteStart := Place;
  1698. end; { TValueCell.OverwriteStart }
  1699.  
  1700. procedure TValueCell.EditString(MaxDecPlaces : Byte;
  1701.                                      var Input : String);
  1702. var
  1703.   S : String;
  1704. begin
  1705.   Str(Value:1:MaxDecPlaces, S);
  1706.   Input := S;
  1707. end; { TValueCell.EditString }
  1708.  
  1709. function TValueCell.DisplayString(FormulasDisplayed : Boolean;
  1710.                                        MaxDecPlaces : Byte) : String;
  1711. var
  1712.   S : String;
  1713. begin
  1714.   Str(Value:1:MaxDecPlaces, S);
  1715.   DisplayString := S;
  1716. end; { TValueCell.DisplayString }
  1717.  
  1718. function TValueCell.FormattedString(var OHash : TOverWriteHashTable;
  1719.                                    var FHash : TFormatHashTable;
  1720.                                    var WHash : TWidthHashTable;
  1721.                                    GetColWidth : GetColWidthFunc;
  1722.                                    CPos : CellPos;
  1723.                                    FormulasDisplayed : Boolean;
  1724.                                    Start : Word; ColWidth : Byte;
  1725.                                    var CurrencyString : CurrencyStr;
  1726.                                    var ClType: CellTypes): String;
  1727. var
  1728.   Counter : Word;
  1729.   S : String;
  1730.   F : FormatType;
  1731. begin
  1732.   ClType := CellType;
  1733.   F := Format(FHash, FormulasDisplayed);
  1734.   Str(Value:1:F and DecPlacesPart, S);
  1735.   if (Start = 1) and ((F and CurrencyPart) <> 0) then
  1736.     CurrencyString := ' '+Char((F and CurrencyCharPart) shr 8)+' '
  1737.   else
  1738.     CurrencyString := '';
  1739.   if (F and CommasPart) <> 0 then
  1740.   begin
  1741.     Counter := Pos('.', S);
  1742.     if Counter = 0 then
  1743.       Counter := System.Length(S);
  1744.     while Counter > 4 do
  1745.     begin
  1746.       System.Insert(',', S, Counter - 3);
  1747.       Dec(Counter, 3);
  1748.     end;
  1749.   end;
  1750.   S := Copy(S, Start, ColWidth);
  1751.   if Length(S) <= (ColWidth - 1) then
  1752.     FormattedString := S + ' '
  1753.   else
  1754.     FormattedString := S;
  1755.  
  1756. end; { TValueCell.FormattedString }
  1757.  
  1758. function TValueCell.CopyString : String;
  1759. begin
  1760.   CopyString := '';
  1761. end; { TValueCell.CopyString }
  1762.  
  1763. constructor TValueCell.Load(var S : TStream);
  1764. begin
  1765.   S.Read(Loc, SizeOf(Loc));
  1766.   S.Read(Error, SizeOf(Error));
  1767.   S.Read(Value, SizeOf(Value));
  1768. end; { TValueCell.Load }
  1769.  
  1770. procedure TValueCell.Store(var S : TStream);
  1771. begin
  1772.   S.Write(Loc, SizeOf(Loc));
  1773.   S.Write(Error, SizeOf(Error));
  1774.   S.Write(Value, SizeOf(Value));
  1775. end; { TValueCell.Store }
  1776.  
  1777.  
  1778. {** TTextCell **}
  1779.  
  1780. constructor TTextCell.Init(InitLoc : CellPos; InitTxt : String);
  1781. begin
  1782.   TCell.Init(InitLoc);
  1783.   Txt.Init;
  1784.   Txt.FromString(InitTxt);
  1785. end; { TTextCell.Init }
  1786.  
  1787. function TTextCell.CellType : CellTypes;
  1788. begin
  1789.   CellType := ClText;
  1790. end; { TTextCell.CellType }
  1791.  
  1792. function TTextCell.LegalValue : Boolean;
  1793. begin
  1794.   LegalValue := False;
  1795. end; { TTextCell.LegalValue }
  1796.  
  1797. function TTextCell.Name : String;
  1798. begin
  1799.   Name := GLStringList^.Get(sTextCellName);
  1800. end; { TTextCell.Name }
  1801.  
  1802. function TTextCell.Format(var FHash : TFormatHashTable;
  1803.                              FormulasDisplayed : Boolean) : FormatType;
  1804. var
  1805.   F : FormatType;
  1806. begin
  1807.   if FHash.Search(Loc, F) then
  1808.     Format := F
  1809.   else
  1810.     Format := 0;
  1811. end; { TTextCell.Format }
  1812.  
  1813. function TTextCell.Width(var FHash : TFormatHashTable;
  1814.                             FormulasDisplayed : Boolean) : Word;
  1815. begin
  1816.   Width := Txt.Length;
  1817. end; { TTextCell.Width }
  1818.  
  1819. function TTextCell.Overwritten(var CHash : TCellHashTable;
  1820.                                    var FHash : TFormatHashTable;
  1821.                                    var WHash : TWidthHashTable;
  1822.                                    var LastPos : CellPos;
  1823.                                    MaxCols : Word;
  1824.                                    GetColWidth : GetColWidthFunc;
  1825.                                    FormulasDisplayed : Boolean) : Word;
  1826. var
  1827.   CellWidth : Longint;
  1828.   Total : Word;
  1829.   P : CellPos;
  1830. begin
  1831.   P := Loc;
  1832.   CellWidth := Width(FHash, FormulasDisplayed);
  1833.   Total := 0;
  1834.   repeat
  1835.     Inc(Total);
  1836.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  1837.     Inc(P.Col);
  1838.   until (CellWidth <= 0) or (P.Col > MaxCols) or (CHash.Search(P) <> Empty);
  1839.   Dec(Total);
  1840.   Overwritten := Total;
  1841. end; { TTextCell.Overwritten }
  1842.  
  1843. function TTextCell.ShouldUpdate : Boolean;
  1844. begin
  1845.   ShouldUpdate := False;
  1846. end; { TTextCell.ShouldUpdate }
  1847.  
  1848. function TTextCell.HasError : Boolean;
  1849. begin
  1850.   HasError := False;
  1851. end; { TTextCell.HasError }
  1852.  
  1853. function TTextCell.CurrValue : Extended;
  1854. begin
  1855.   CurrValue := 0;
  1856. end; { TTextCell.CurrValue }
  1857.  
  1858. function TTextCell.OverwriteStart(var FHash : TFormatHashTable;
  1859.                                  var WHash : TWidthHashTable;
  1860.                                  GetColWidth : GetColWidthFunc;
  1861.                                  EndCol : Word;
  1862.                                  DisplayFormulas : Boolean) : Word;
  1863. var
  1864.   F : FormatType;
  1865.   C, Place : Word;
  1866. begin
  1867.   F := Format(FHash, DisplayFormulas);
  1868.   Place := 1;
  1869.   C := Loc.Col;
  1870.   repeat
  1871.     Inc(Place, GetColWidth(WHash, C));
  1872.     Inc(C);
  1873.   until C = EndCol;
  1874.   OverwriteStart := Place;
  1875. end; { TTextCell.OverwriteStart }
  1876.  
  1877. procedure TTextCell.EditString(MaxDecPlaces : Byte;
  1878.                               var Input : String);
  1879. begin
  1880.    Input := Txt.ToString;
  1881. end; { TTextCell.EditString }
  1882.  
  1883. function TTextCell.DisplayString(FormulasDisplayed : Boolean;
  1884.                                       MaxDecPlaces : Byte) : String;
  1885. begin
  1886.   DisplayString := Txt.Copy(2, (Txt.Length)-1);
  1887. end; { TTextCell.DisplayString }
  1888.  
  1889. function TTextCell.FormattedString(var OHash : TOverWriteHashTable;
  1890.                                   var FHash : TFormatHashTable;
  1891.                                   var WHash : TWidthHashTable;
  1892.                                   GetColWidth : GetColWidthFunc;
  1893.                                   CPos : CellPos;
  1894.                                   FormulasDisplayed : Boolean;
  1895.                                   Start : Word; ColWidth : Byte;
  1896.                                   var CurrencyString : CurrencyStr;
  1897.                                   var ClType: CellTypes): String;
  1898. begin
  1899.   ClType := CellType;
  1900.   CurrencyString := '';
  1901.   FormattedString := Txt.Copy(Succ(Start), ColWidth);
  1902. end; { TTextCell.FormattedString }
  1903.  
  1904. function TTextCell.CopyString : String;
  1905. begin
  1906.   CopyString := Txt.ToString;
  1907. end; { TTextCell.CopyString }
  1908.  
  1909. constructor TTextCell.Load(var S : TStream);
  1910. begin
  1911.   S.Read(Loc, SizeOf(Loc));
  1912.   Txt.Load(S);
  1913. end; { TTextCell.Load }
  1914.  
  1915. procedure TTextCell.Store(var S : TStream);
  1916. begin
  1917.   S.Write(Loc, SizeOf(Loc));
  1918.   Txt.Store(S);
  1919. end; { TTextCell.Store }
  1920.  
  1921. destructor TTextCell.Done;
  1922. begin
  1923.    Txt.Done;
  1924. end;
  1925.  
  1926.  
  1927.  
  1928. {** TFormulaCell **}
  1929.  
  1930. constructor TFormulaCell.Init(InitLoc : CellPos; InitError : Boolean;
  1931.                              InitValue : Extended; InitFormula : String);
  1932. begin
  1933.   TCell.Init(InitLoc);
  1934.   Formula.Init;
  1935.   Formula.FromString(InitFormula);
  1936.   Error := InitError;
  1937.   Value := InitValue;
  1938. end; { TFormulaCell.Init }
  1939.  
  1940. function TFormulaCell.CellType : CellTypes;
  1941. begin
  1942.   CellType := ClFormula;
  1943. end; { TFormulaCell.CellType }
  1944.  
  1945. function TFormulaCell.LegalValue : Boolean;
  1946. begin
  1947.   LegalValue := True;
  1948. end; { TFormulaCell.LegalValue }
  1949.  
  1950. function TFormulaCell.Name : String;
  1951. begin
  1952.   Name := GLStringList^.Get(sFormulaCellName);
  1953. end; { TFormulaCell.Name }
  1954.  
  1955. function TFormulaCell.Format(var FHash : TFormatHashTable;
  1956.                                 FormulasDisplayed : Boolean) : FormatType;
  1957. var
  1958.   F : FormatType;
  1959. begin
  1960.   if FHash.Search(Loc, F) then
  1961.     Format := F
  1962.   else if FormulasDisplayed then
  1963.     Format := 0
  1964.   else
  1965.     Format := (Ord(JRight) shl 4) + DefaultDefaultDecimalPlaces;
  1966. end; { TFormulaCell.Format }
  1967.  
  1968. function TFormulaCell.Width(var FHash : TFormatHashTable;
  1969.                                FormulasDisplayed : Boolean) : Word;
  1970. var
  1971.   S : String;
  1972.   F : FormatType;
  1973.   P, W : Word;
  1974. begin
  1975.   if FormulasDisplayed then
  1976.     Width := Formula.Length
  1977.   else begin
  1978.     F := Format(FHash, FormulasDisplayed);
  1979.     Str(Value:1:(F and DecPlacesPart), S);
  1980.     W := Length(S);
  1981.     if (F and CurrencyPart) <> 0 then
  1982.       Inc(W, Length(DefaultCurrencyString));
  1983.     if (F and CommasPart) <> 0 then
  1984.     begin
  1985.       P := Pos('.', S);
  1986.       if P = 0 then
  1987.         P := Length(S);
  1988.       Inc(W, (P - 2) div 3);
  1989.     end;
  1990.     Width := W;
  1991.   end;
  1992. end; { TFormulaCell.Width }
  1993.  
  1994. function TFormulaCell.Overwritten(var CHash : TCellHashTable;
  1995.                                       var FHash : TFormatHashTable;
  1996.                                       var WHash : TWidthHashTable;
  1997.                                       var LastPos : CellPos;
  1998.                                       MaxCols : Word;
  1999.                                       GetColWidth : GetColWidthFunc;
  2000.                                       FormulasDisplayed : Boolean) : Word;
  2001. var
  2002.   CellWidth : Longint;
  2003.   Total : Word;
  2004.   P : CellPos;
  2005. begin
  2006.   P := Loc;
  2007.   CellWidth := Width(FHash, FormulasDisplayed);
  2008.   Total := 0;
  2009.   repeat
  2010.     Inc(Total);
  2011.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  2012.     Inc(P.Col);
  2013.   until (CellWidth <= 0) or (P.Col > MaxCols) or (CHash.Search(P) <> Empty);
  2014.   Dec(Total);
  2015.   Overwritten := Total;
  2016. end; { TFormulaCell.Overwritten }
  2017.  
  2018. function TFormulaCell.ShouldUpdate : Boolean;
  2019. begin
  2020.   ShouldUpdate := True;
  2021. end; { TFormulaCell.ShouldUpdate }
  2022.  
  2023. function TFormulaCell.HasError : Boolean;
  2024. begin
  2025.   HasError := Error;
  2026. end; { TFormulaCell.HasError }
  2027.  
  2028. function TFormulaCell.CurrValue : Extended;
  2029. begin
  2030.   CurrValue := Value;
  2031. end; { TFormulaCell.CurrValue }
  2032.  
  2033. function TFormulaCell.OverwriteStart(var FHash : TFormatHashTable;
  2034.                                     var WHash : TWidthHashTable;
  2035.                                     GetColWidth : GetColWidthFunc;
  2036.                                     EndCol : Word;
  2037.                                     DisplayFormulas : Boolean) : Word;
  2038. var
  2039.   F : FormatType;
  2040.   C, Place : Word;
  2041. begin
  2042.   F := Format(FHash, DisplayFormulas);
  2043.   Place := 1;
  2044.   C := Loc.Col;
  2045.   repeat
  2046.     Inc(Place, GetColWidth(WHash, C));
  2047.     Inc(C);
  2048.   until C = EndCol;
  2049.   if (not DisplayFormulas) and ((F and CurrencyPart) <> 0) then
  2050.     Dec(Place, Length(DefaultCurrencyString));
  2051.   OverwriteStart := Place;
  2052. end; { TFormulaCell.OverwriteStart }
  2053.  
  2054. procedure TFormulaCell.EditString(MaxDecPlaces : Byte;
  2055.                                   var Input : String);
  2056. begin
  2057.    Input := Formula.ToString;
  2058. end; { TFormulaCell.EditString }
  2059.  
  2060. function TFormulaCell.DisplayString(FormulasDisplayed : Boolean;
  2061.                                          MaxDecPlaces : Byte) : String;
  2062. var
  2063.   S : String;
  2064. begin
  2065.   if not FormulasDisplayed then
  2066.     DisplayString := Formula.ToString
  2067.   else begin
  2068.     Str(Value:1:MaxDecPlaces, S);
  2069.     DisplayString := S;
  2070.   end;
  2071. end; { TFormulaCell.DisplayString }
  2072.  
  2073. function TFormulaCell.FormattedString(var OHash : TOverWriteHashTable;
  2074.                                      var FHash : TFormatHashTable;
  2075.                                      var WHash : TWidthHashTable;
  2076.                                      GetColWidth : GetColWidthFunc;
  2077.                                      CPos : CellPos;
  2078.                                      FormulasDisplayed : Boolean;
  2079.                                      Start : Word; ColWidth : Byte;
  2080.                                      var CurrencyString : CurrencyStr;
  2081.                                      var ClType: CellTypes): String;
  2082. var
  2083.   S : String;
  2084.   Counter : Word;
  2085.   F : FormatType;
  2086. begin
  2087.   ClType := CellType;
  2088.   if FormulasDisplayed then
  2089.   begin
  2090.     CurrencyString := '';
  2091.     FormattedString := Formula.Copy(Start, ColWidth);
  2092.   end
  2093.   else begin
  2094.     F := Format(FHash, FormulasDisplayed);
  2095.     Str(Value:1:F and DecPlacesPart, S);
  2096.     if (Start = 1) and ((F and CurrencyPart) <> 0) then
  2097.       CurrencyString := ' '+Char((F and CurrencyCharPart) shr 8)+' '
  2098.     else
  2099.       CurrencyString := '';
  2100.     if (F and CommasPart) <> 0 then
  2101.     begin
  2102.       Counter := Pos('.', S);
  2103.       if Counter = 0 then
  2104.         Counter := Length(S);
  2105.       while Counter > 4 do
  2106.       begin
  2107.         Insert(',', S, Counter - 3);
  2108.         Dec(Counter, 3);
  2109.       end;
  2110.     end;
  2111.     FormattedString := Copy(S, Start, ColWidth);
  2112.   end;
  2113. end; { TFormulaCell.FormattedString }
  2114.  
  2115. function TFormulaCell.CopyString : String;
  2116. begin
  2117.   CopyString := Formula.ToString;
  2118. end; { TFormulaCell.CopyString }
  2119.  
  2120. constructor TFormulaCell.Load(var S : TStream);
  2121. begin
  2122.   S.Read(Loc, SizeOf(Loc));
  2123.   Formula.Load(S);
  2124. end; { TFormulaCell.Load }
  2125.  
  2126. procedure TFormulaCell.Store(var S : TStream);
  2127. begin
  2128.   S.Write(Loc, SizeOf(Loc));
  2129.   Formula.Store(S);
  2130. end; { TFormulaCell.Store }
  2131.  
  2132. function TFormulaCell.GetFormula : String;
  2133. begin
  2134.   GetFormula := Formula.ToString;
  2135. end; { TFormulaCell.GetFormula }
  2136.  
  2137. destructor TFormulaCell.Done;
  2138. begin
  2139.    Formula.Done;
  2140. end;
  2141.  
  2142.  
  2143.  
  2144. {** TRepeatCell **}
  2145.  
  2146. constructor TRepeatCell.Init(InitLoc : CellPos; InitChar : Char);
  2147. begin
  2148.   TCell.Init(InitLoc);
  2149.   RepeatChar := InitChar;
  2150. end; { TRepeatCell.Init }
  2151.  
  2152. function TRepeatCell.CellType : CellTypes;
  2153. begin
  2154.   CellType := ClRepeat;
  2155. end; { TRepeatCell.CellType }
  2156.  
  2157. function TRepeatCell.LegalValue : Boolean;
  2158. begin
  2159.   LegalValue := False;
  2160. end; { TRepeatCell.LegalValue }
  2161.  
  2162. function TRepeatCell.Name : String;
  2163. begin
  2164.   Name := GLStringList^.Get(sRepeatCellName);
  2165. end; { TRepeatCell.Name }
  2166.  
  2167. function TRepeatCell.Format(var FHash : TFormatHashTable;
  2168.                                FormulasDisplayed : Boolean) : FormatType;
  2169. begin
  2170.   Format := 0;
  2171. end; { TRepeatCell.Format }
  2172.  
  2173. function TRepeatCell.Width(var FHash : TFormatHashTable;
  2174.                               FormulasDisplayed : Boolean) : Word;
  2175. begin
  2176.   Width := 2;
  2177. end; { TRepeatCell.Width }
  2178.  
  2179. function TRepeatCell.Overwritten(var CHash : TCellHashTable;
  2180.                                 var FHash : TFormatHashTable;
  2181.                                 var WHash : TWidthHashTable;
  2182.                                 var LastPos : CellPos;
  2183.                                 MaxCols : Word;
  2184.                                 GetColWidth : GetColWidthFunc;
  2185.                                 FormulasDisplayed : Boolean) : Word;
  2186. var
  2187.   Total : Word;
  2188.   P : CellPos;
  2189. begin
  2190.   P := Loc;
  2191.   Total := 0;
  2192.   repeat
  2193.     Inc(Total);
  2194.     Inc(P.Col);
  2195.   until (P.Col > LastPos.Col) or (CHash.Search(P) <> Empty) or
  2196.         (P.Col = 0);
  2197.   Dec(Total);
  2198.   if (P.Col > LastPos.Col) or (P.Col = 0) then
  2199.     Total := MaxCols - Loc.Col;
  2200.   Overwritten := Total;
  2201. end; { TRepeatCell.Overwritten }
  2202.  
  2203. function TRepeatCell.ShouldUpdate : Boolean;
  2204. begin
  2205.   ShouldUpdate := False;
  2206. end; { TRepeatCell.ShouldUpdate }
  2207.  
  2208. function TRepeatCell.HasError : Boolean;
  2209. begin
  2210.   HasError := False;
  2211. end; { TRepeatCell.HasError }
  2212.  
  2213. function TRepeatCell.CurrValue : Extended;
  2214. begin
  2215.   CurrValue := 0;
  2216. end; { TRepeatCell.CurrValue }
  2217.  
  2218. function TRepeatCell.OverwriteStart(var FHash : TFormatHashTable;
  2219.                                    var WHash : TWidthHashTable;
  2220.                                    GetColWidth : GetColWidthFunc;
  2221.                                    EndCol : Word;
  2222.                                    DisplayFormulas : Boolean) : Word;
  2223. begin
  2224.   OverwriteStart := 1;
  2225. end; { TRepeatCell.OverwriteStart }
  2226.  
  2227. procedure TRepeatCell.EditString(MaxDecPlaces : Byte;
  2228.                                 var Input : String);
  2229. var
  2230.   Good : Boolean;
  2231. begin
  2232.   Input := RepeatFirstChar + RepeatChar;
  2233. end; { TRepeatCell.EditString }
  2234.  
  2235. function TRepeatCell.DisplayString(FormulasDisplayed : Boolean;
  2236.                                         MaxDecPlaces : Byte) : String;
  2237. begin
  2238.   DisplayString := FillString(ScreenCols, RepeatChar);
  2239. end; { TRepeatCell.DisplayString }
  2240.  
  2241. function TRepeatCell.FormattedString(var OHash : TOverWriteHashTable;
  2242.                                     var FHash : TFormatHashTable;
  2243.                                     var WHash : TWidthHashTable;
  2244.                                     GetColWidth : GetColWidthFunc;
  2245.                                     CPos : CellPos;
  2246.                                     FormulasDisplayed : Boolean;
  2247.                                     Start : Word; ColWidth : Byte;
  2248.                                     var CurrencyString : CurrencyStr;
  2249.                                     var ClType: CellTypes): String;
  2250. begin
  2251.   ClType := CellType;
  2252.   CurrencyString := '';
  2253.   FormattedString := PadChar('', RepeatChar, ColWidth);
  2254. end; { TRepeatCell.FormattedString }
  2255.  
  2256. function TRepeatCell.CopyString : String;
  2257. var
  2258.    Input : String;
  2259. begin
  2260.   EditString(0, Input);
  2261.   CopyString := Input;
  2262. end; { TRepeatCell.CopyString }
  2263.  
  2264. constructor TRepeatCell.Load(var S : TStream);
  2265. begin
  2266.   S.Read(Loc, SizeOf(Loc));
  2267.   S.Read(RepeatChar, SizeOf(RepeatChar));
  2268. end; { TRepeatCell.Load }
  2269.  
  2270. procedure TRepeatCell.Store(var S : TStream);
  2271. begin
  2272.   S.Write(Loc, SizeOf(Loc));
  2273.   S.Write(RepeatChar, SizeOf(RepeatChar));
  2274. end; { TRepeatCell.Store }
  2275.  
  2276.  
  2277. {** THeadersHashTable **}
  2278.  
  2279. constructor THeadersHashTable.Init(InitBuckets : BucketRange);
  2280. { Initializes the column names hash table, which stores specific
  2281.   column namess, different to the normal letter headings }
  2282. begin
  2283.   if not THashTable.Init(InitBuckets) then
  2284.     Fail;
  2285. end; {...THeadersHashTable.Init }
  2286.  
  2287.  
  2288.  
  2289. function THeadersHashTable.Add(SCol : Word; NewName: String) : Boolean;
  2290. begin
  2291.   CurrCol := SCol;
  2292.   CurrName := NewName;
  2293.   Add := THashTable.Add;
  2294. end; {...THeadersHashTable.Add }
  2295.  
  2296.  
  2297.  
  2298. procedure THeadersHashTable.CreateItem(var Item : HashItemPtr);
  2299. begin
  2300.   Move(CurrCol, Item^.Data, SizeOf(CurrCol));
  2301.   Move(CurrName, Item^.Data[SizeOf(CurrCol)], SizeOf(CurrName));
  2302. end; {...THeadersHashTable.CreateItem }
  2303.  
  2304.  
  2305. procedure THeadersHashTable.Delete(Col : Word);
  2306. begin
  2307.   CurrCol := Col;
  2308.   THashTable.Delete(nil);
  2309. end; {...THeadersHashTable.Delete }
  2310.  
  2311.  
  2312.  
  2313. function THeadersHashTable.Found(Item : HashItemPtr) : Boolean;
  2314. var
  2315.   C : Word;
  2316. begin
  2317.   Move(Item^.Data, C, SizeOf(C));
  2318.   Found := CurrCol = C
  2319. end; {...THeadersHashTable.Found }
  2320.  
  2321.  
  2322.  
  2323. function THeadersHashTable.HashValue : LongInt;
  2324. begin
  2325.   HashValue := CurrCol;
  2326. end; {...THeadersHashTable.HashValue }
  2327.  
  2328.  
  2329.  
  2330. function THeadersHashTable.ItemSize : HashItemSizeRange;
  2331. begin
  2332.   ItemSize := SizeOf(CurrCol) + SizeOf(CurrName);
  2333. end; { THeadersHashTable.ItemSize }
  2334.  
  2335.  
  2336.  
  2337. procedure THeadersHashTable.Load(var S : TStream; Total : Longint);
  2338. var
  2339.   Counter : Longint;
  2340.   Col : Word;
  2341.   Header : String[80];
  2342. begin
  2343.   for Counter := 1 to Total do
  2344.   begin
  2345.     S.Read(Col, SizeOf(Col));
  2346.     S.Read(Header, SizeOf(Header));
  2347.     if not Add(Col, Header) then
  2348.     begin
  2349.       S.Error(stNoMemoryError, 0);
  2350.       Exit;
  2351.     end; {...if not Add(Col, Name) }
  2352.   end; {...for Counter }
  2353. end; {...THeadersHashTable.Load }
  2354.  
  2355.  
  2356.  
  2357. function THeadersHashTable.Search(Col : Word;
  2358.                                var Name: String) : Boolean;
  2359. var
  2360.   I : HashItemPtr;
  2361. begin
  2362.   CurrCol := Col;
  2363.   I := THashTable.Search;
  2364.   if I = NIL then
  2365.      Search := False
  2366.   else
  2367.      begin
  2368.         Search := True;
  2369.         Move(I^.Data[SizeOf(CurrCol)], Name, SizeOf(Name))
  2370.      end; {...else/if I = NIL }
  2371. end; {...THeadersHashTable.Search }
  2372.  
  2373.  
  2374.  
  2375. function THeadersHashTable.SearchName(Name: String;
  2376.                                var Col: Word): Boolean;
  2377. var
  2378.    H : HashItemPtr;
  2379. begin
  2380.    SearchName := False;
  2381.    Col := 0;
  2382.    H := FirstItem;
  2383.    while H <> NIL do
  2384.    begin
  2385.       Move(H^.Data[SizeOf(CurrCol)], CurrName, SizeOf(CurrName));
  2386.       if UpperCase(CurrName) = UpperCase(Name) then
  2387.          begin
  2388.             Move(H^.Data, CurrCol, SizeOf(CurrCol));
  2389.             Col := CurrCol;
  2390.             SearchName := True;
  2391.             H := NIL;
  2392.          end {...if UpperCase(CurrName) = UpperCase(Name) }
  2393.       else
  2394.          H := NextItem;
  2395.    end; {...while H <> NIL }
  2396. end; {...THeadersHashTable.SearchName }
  2397.  
  2398. procedure THeadersHashTable.Store(var S : TStream);
  2399. var
  2400.   H : HashItemPtr;
  2401.   Col : Word;
  2402.   Header : String[80];
  2403. begin
  2404.   H := FirstItem;
  2405.   while H <> nil do
  2406.   begin
  2407.     Move(H^.Data, Col, SizeOf(Col));
  2408.     S.Write(Col, SizeOf(Col));
  2409.     Move(H^.Data[SizeOf(Col)], Header, SizeOf(Header));
  2410.     S.Write(Header, SizeOf(Header));
  2411.     H := NextItem;
  2412.   end;
  2413. end; {...THeadersHashTable.Store }
  2414.  
  2415.  
  2416.  
  2417. destructor THeadersHashTable.Done;
  2418. begin
  2419.   THashTable.Done;
  2420. end; {...THeadersHashTable.Done }
  2421.  
  2422.  
  2423.  
  2424. {** TUnlockedHashTable **}
  2425.  
  2426. constructor TUnlockedHashTable.Init;
  2427. { Inits a TBlockedCellHashTable that keeps track of which cells are
  2428.   marked as LOCKED }
  2429. begin
  2430.    if not HashTable.Init(1) then
  2431.       Fail;
  2432. end; {...TUnlockedHashTable.Init }
  2433.  
  2434.  
  2435.  
  2436. function TUnlockedHashTable.Add(NewStart, NewStop: CellPos): Boolean;
  2437. { Adds a group of cells to the hash table.  If it is found in this
  2438.   hash table, then the cell is considered locked }
  2439. begin
  2440.    if (not Search(NewStart)) or (not Search(NewStop)) then
  2441.    begin
  2442.       if not Overwrite(NewStart, NewStop) then
  2443.       begin
  2444.          Add := False;
  2445.          Exit;
  2446.       end; {...if not Overwrite(NewStart, NewStop) }
  2447.       CurrStart := NewStart;
  2448.       CurrStop := NewStop;
  2449.       Add := HashTable.Add;
  2450.    end; {...if (not Search(NewStart) or (not Search(NewStop)) }
  2451. end; {...TUnlockedHashTable.Add }
  2452.  
  2453.  
  2454.  
  2455. procedure TUnlockedHashTable.CreateItem(var Item: HashItemPtr);
  2456. begin
  2457.   with Item^ do
  2458.   begin
  2459.     Move(CurrStart, Data, SizeOf(CellPos));
  2460.     Move(CurrStop, Data[SizeOf(CellPos)], SizeOf(CellPos));
  2461.   end; {...with Item^ }
  2462. end; {...TUnlockedHashTable.CreateItem }
  2463.  
  2464.  
  2465.  
  2466. function TUnlockedHashTable.Delete(DStart, DStop: CellPos): Boolean;
  2467. begin
  2468.    Delete := Overwrite(DStart, DStop);
  2469. end; {...TUnlockedHashTable.Delete }
  2470.  
  2471.  
  2472.  
  2473. function TUnlockedHashTable.Found(Item: HashItemPtr): Boolean;
  2474. var
  2475.   P : CellPos;
  2476.   B : TBlock;
  2477.   Start, Stop : CellPos;
  2478.   Good : Boolean;
  2479. begin
  2480.   Move(Item^.Data, Start, SizeOf(CellPos));
  2481.   Move(Item^.Data[SizeOf(CellPos)], Stop, SizeOf(CellPos));
  2482.   B.Init(Start);
  2483.   B.Stop := Stop;
  2484.   Found := B.CellInBlock(CurrStart);
  2485. end; {...TUnlockedHashTable.Found }
  2486.  
  2487.  
  2488.  
  2489. function TUnlockedHashTable.HashValue : LongInt;
  2490. begin
  2491.    HashValue := 1;
  2492. end; {...TUnlockedHashTable.HashValue }
  2493.  
  2494.  
  2495.  
  2496. function TUnlockedHashTable.ItemSize : HashItemSizeRange;
  2497. begin
  2498.    ItemSize := (SizeOf(CellPos) shl 1);
  2499. end; {...TUnlockedHashTable.ItemSize }
  2500.  
  2501.  
  2502. constructor TUnlockedHashTable.Load(var S: TStream; Total: Longint);
  2503. var
  2504.    Counter : LongInt;
  2505.    C1, C2 : CellPos;
  2506. begin
  2507.    for Counter := 1 to Total do
  2508.    begin
  2509.       S.Read(C1, SizeOf(C1));
  2510.       S.Read(C2, SizeOf(C2));
  2511.       if not Add(C1, C2) then
  2512.       begin
  2513.          S.Error(stNoMemoryError, 0);
  2514.          Exit;
  2515.       end; {...if not Add(C1, C2) }
  2516.    end; {...for Counter }
  2517. end; {...TUnlockedHashTable.Load }
  2518.  
  2519.  
  2520.  
  2521.  
  2522. function TUnlockedHashTable.Overwrite(NewStart, NewStop : CellPos) : Boolean;
  2523. { Checks to see if a new locked area has overwritten an old one, requiring
  2524.   the old area to be overwritten or broken into parts }
  2525. var
  2526.   H, Next : HashItemPtr;
  2527.   AStart, AStop, BStart, BStop : CellPos;
  2528.   F : FormatType;
  2529.   P : CellPos;
  2530.   Added : Boolean;
  2531. begin
  2532.   Overwrite := False;
  2533.   H := HashData^[1];
  2534.   while H <> nil do
  2535.   begin
  2536.     Next := H^.Next;
  2537.     Move(H^.Data, BStart, SizeOf(CellPos));
  2538.     Move(H^.Data[SizeOf(CellPos)], BStop, SizeOf(CellPos));
  2539.     if ((((NewStart.Col >= BStart.Col) and (NewStart.Col <= BStop.Col)) or
  2540.          ((NewStop.Col >= BStart.Col) and (NewStop.Col <= BStop.Col))) and
  2541.         (((NewStart.Row >= BStart.Row) and (NewStart.Row <= BStop.Row)) or
  2542.          ((NewStop.Row >= BStart.Row) and (NewStop.Row <= BStop.Row)))) or
  2543.        ((((BStart.Col >= NewStart.Col) and (BStart.Col <= NewStop.Col)) or
  2544.          ((BStop.Col >= NewStart.Col) and (BStop.Col <= NewStop.Col))) and
  2545.         (((BStart.Row >= NewStart.Row) and (BStart.Row <= NewStop.Row)) or
  2546.          ((BStop.Row >= NewStart.Row) and (BStop.Row <= NewStop.Row)))) then
  2547.     begin
  2548.       Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
  2549.       CurrStart := BStart;
  2550.       CurrStop := BStop;
  2551.       THashTable.Delete(nil);
  2552.       if BStart.Row < NewStart.Row then
  2553.       begin
  2554.         AStart := BStart;
  2555.         AStop.Col := BStop.Col;
  2556.         AStop.Row := Pred(NewStart.Row);
  2557.         if not Add(AStart, AStop) then
  2558.           Exit;
  2559.       end;
  2560.       if BStop.Row > NewStop.Row then
  2561.       begin
  2562.         AStart.Col := BStart.Col;
  2563.         AStart.Row := Succ(NewStop.Row);
  2564.         AStop.Col := BStop.Col;
  2565.         AStop.Row := BStop.Row;
  2566.         if not Add(AStart, AStop) then
  2567.           Exit;
  2568.       end;
  2569.       if BStart.Col < NewStart.Col then
  2570.       begin
  2571.         AStart.Col := BStart.Col;
  2572.         AStart.Row := Max(BStart.Row, NewStart.Row);
  2573.         AStop.Col := Pred(NewStart.Col);
  2574.         AStop.Row := Min(BStop.Row, NewStop.Row);
  2575.         if not Add(AStart, AStop) then
  2576.           Exit;
  2577.       end;
  2578.       if BStop.Col > NewStop.Col then
  2579.       begin
  2580.         AStart.Col := Succ(NewStop.Col);
  2581.         AStart.Row := Max(BStart.Row, NewStart.Row);
  2582.         AStop.Col := BStop.Col;
  2583.         AStop.Row := Min(BStop.Row, NewStop.Row);
  2584.         if not Add(AStart, AStop) then
  2585.           Exit;
  2586.       end;
  2587.     end;
  2588.     H := Next;
  2589.   end;
  2590.   Overwrite := True;
  2591. end; {...TUnlockedHashTable.Overwrite }
  2592.  
  2593.  
  2594.  
  2595. function TUnlockedHashTable.Search(SPos: CellPos): Boolean;
  2596. var
  2597.    H : HashItemPtr;
  2598. begin
  2599.    CurrStart := SPos;
  2600.    H := HashTable.Search;
  2601.    if H = NIL then
  2602.       Search := False
  2603.    else
  2604.       Search := True;
  2605. end; {...TUnlockedHashTable.Search }
  2606.  
  2607.  
  2608.  
  2609. procedure TUnlockedHashTable.Store(var S: TStream);
  2610. var
  2611.    H : HashItemPtr;
  2612.    C : CellPos;
  2613. begin
  2614.    H := FirstItem;
  2615.    while H <> NIL do
  2616.    begin
  2617.       Move(H^.Data, C, SizeOf(C));
  2618.       S.Write(C, SizeOf(C));
  2619.       Move(H^.Data[SizeOf(CellPos)], C, SizeOf(C));
  2620.       S.Write(C, SizeOf(C));
  2621.       H := NextItem;
  2622.    end; {...while H <> NIL }
  2623. end; {...TUnlockedHashTable.Store }
  2624.  
  2625. destructor TUnlockedHashTable.Done;
  2626. begin
  2627.    HashTable.Done;
  2628. end; {...TUnlockedHashTable.Done }
  2629.  
  2630.  
  2631. {****************************************************************************}
  2632. {**                            Exit Procedure                              **}
  2633. {****************************************************************************}
  2634.  
  2635. procedure CellExit;
  2636. { Removes Empty cell from memory, restores ExitProc }
  2637. begin
  2638.   Dispose(Empty, Done);
  2639.   ExitProc := SavedExitProc;
  2640. end; { CellExit }
  2641.  
  2642. {****************************************************************************}
  2643. {**                    Unit's initialization Section                       **}
  2644. {****************************************************************************}
  2645.  
  2646. begin
  2647.   SavedExitProc := ExitProc;
  2648.   ExitProc := @CellExit;
  2649.   Empty := New(PEmptyCell, Init);
  2650. end.